下面的代码是我正在处理的实际代码的极端简化。这只适合任何人重现我所面临的问题。
#include <mutex>
#include <thread>
using std::mutex;
using std::thread;
void Do()
{
static mutex myMutex;
static int dataToProtect;
return;
}
class MyClass
{
public:
~MyClass()
{
mythread_.join();
}
void RunMyThread()
{
mythread_ = thread(&Do);
}
static MyClass *Instance()
{
static MyClass single;
return &single;
}
private:
MyClass()
{}
std::thread mythread_;
};
int main()
{
MyClass::Instance()->RunMyThread();
return 0;
}
在MinGW-w64上遵守gcc时,执行陷入:
static mutex myMutex;
看起来线程和单例设计的组合会产生这个问题,因为如果我在不使用线程的情况下调用Do():
void RunMyThread()
{
// mythread_ = thread(&Do);
Do();
}
程序执行到最后。 或者,如果我通过使构造函数公开来解决单例设计问题,并通过MyClass实例调用RunMyThread():
int main()
{
// MyClass::Instance()->RunMyThread();
MyClass o;
o.RunMyThread();
return 0;
}
程序也会执行到最后。
现在,如果我在Linux上使用gcc在顶部编译原始代码,则没有问题。程序执行到最后。
我无法弄清楚此代码中的哪些行为与平台有关。任何的想法?
答案 0 :(得分:1)
这很可能是由Windows运行时清理内容的顺序引起的。你可以通过向你的类添加一个显式调用来测试这个:
ShutDown()
{
mythread_.join();
}
从析构函数中取出join调用。然后在你的主要功能:
int main()
{
MyClass::Instance()->RunMyThread();
MyClass::Instance()->ShutDown();
return 0;
}
答案 1 :(得分:1)
考虑到之前的评论/答案,问题的一个简单答案是:在主函数返回后允许线程执行是导致未定义行为的原因。 (如果要求代码可移植性,则应避免这种情况。)