最近几天我一直在研究一个奇怪的分段错误。以下代码在我运行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();
}
答案 0 :(得分:0)
请勿使用-lpthread
。这仅与提供线程处理功能的库链接。全线程支持可能需要更多,例如,使用特殊的线程安全版本的libstdc ++进行链接,或者为线程局部变量访问保留特定的寄存器。
使用gcc或g ++,使用-pthread
命令行标志,用于编译和链接。这将指示gcc执行任何必要的操作以启用可靠的线程,包括但不限于在需要时添加-lpthread
标志。
答案 1 :(得分:0)
我很久以前就已经解决了这个问题(几年;-)),但忘了发布解决方案。
这个问题是由这个古老的 GCC 版本中的编译器错误引起的。使用 try..catch 可以解决一些恶意汇编指令,这些指令会在多种情况下导致访问冲突。
我想它在几年前已在 GCC 中修复,但对于我们(我们被迫使用这个旧版本)来说,解决方案是使用编译器标志 -fno-exceptions
来解决这个问题。