具有posix线程的嵌入式ARM上的奇怪分段故障需要智能答案

时间:2010-10-18 10:20:17

标签: c++ linux arm segmentation-fault

最近几天我一直在研究一个奇怪的分段错误。以下代码在我运行Linux的PC上运行正常。但是使用我们的嵌入式设备制造商提供的ARM交叉编译器,它会在例程s()中产生分段错误。 SIGSEGV发生在std :: string的销毁中。如果将其作为变量传递,也会发生这种情况。但是,对于非STL类(例如int),一切正常。

使用ARM交叉编译器编译代码


arm-linux-g++ -Wall -otest -lpthread
arm-linux-strip test

欢迎所有建议!


using namespace std;

void *ExecuteThreadMethod(void *AThread);

class Thread
{
  private:
    pthread_t internalThread;
    sem_t finishedSemaphore;
  public:
    bool Terminated;
    Thread()
    {
      Terminated = false;
      sem_init (&finishedSemaphore, 0, 0);
    }
    ~Thread()
    {
      sem_destroy (&finishedSemaphore);
    }

    void RunSigSegv() // <----- with the try...catch it causes a SIGSEGV in routine s() below
    {
      try
      {
        while (!Terminated)
        {
          cout << "ExecuteLooped" << endl;
        }
        sem_post(&finishedSemaphore);
      }
      catch(...)
      {
      }
    }

    void RunOk() // <----- without the try...catch, it runs fine
    {
      while (!Terminated)
      {
        cout << "ExecuteLooped" << endl;
      }
      sem_post(&finishedSemaphore);
    }

    void Start()
    {
      pthread_attr_t _attr;

      pthread_attr_init(&_attr);
      pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_DETACHED);
      pthread_create (&internalThread, &_attr, ExecuteThreadMethod, this);
    }

    void Terminate()
    {
      Terminated = true;
      sem_wait(&finishedSemaphore);
    }
};

void *ExecuteThreadMethod(void *AThread)
{
  ((Thread *)AThread)->RunSigSegv();
  pthread_exit(NULL);
}

Thread _thread;

void s()
{
  string Test;
  _thread.Start();
} // <----- destruction of std::string Test causes a SIGSEGV, without try...catch in the thread this doesn't happen

void t()
{
  _thread.Terminate();
}

int main(void)
{
  s();
  t();
}

2 个答案:

答案 0 :(得分:0)

请勿使用-lpthread。这仅与提供线程处理功能的库链接。全线程支持可能需要更多,例如,使用特殊的线程安全版本的libstdc ++进行链接,或者为线程局部变量访问保留特定的寄存器。

使用gcc或g ++,使用-pthread命令行标志,用于编译和链接。这将指示gcc执行任何必要的操作以启用可靠的线程,包括但不限于在需要时添加-lpthread标志。

答案 1 :(得分:0)

我很久以前就已经解决了这个问题(几年;-)),但忘了发布解决方案。

这个问题是由这个古老的 GCC 版本中的编译器错误引起的。使用 try..catch 可以解决一些恶意汇编指令,这些指令会在多种情况下导致访问冲突。

我想它在几年前已在 GCC 中修复,但对于我们(我们被迫使用这个旧版本)来说,解决方案是使用编译器标志 -fno-exceptions 来解决这个问题。