有一个EventHandler类的单例对象来接收来自mainthread的事件。它将输入注册到向量并创建一个运行lambda函数的线程,该函数在从向量中删除输入之前等待一段时间,以防止在一段时间内重复执行该输入的事件。
但是我在忙碌的错误中被摧毁了互联网。我不确定它发生在哪里以及它是如何发生的。我甚至不确定它是什么意思,因为它不应该被解构为单身对象。一些帮助将不胜感激。
class EventHandler{
public:
std::mutex simpleLock;
std::vector<UInt32> stuff;
void RegisterBlock(UInt32 input){
stuff.push_back(input);
std::thread removalCallBack([&](UInt32 input){
std::this_thread::sleep_for(std::chrono::milliseconds(200));
simpleLock.lock();
auto it = Find(stuff, input);
if (it != stuff.end())
stuff.erase(it);
simpleLock.simpleLock.unlock();
}, input)
removalCallBack.detach();
}
virtual EventResult ReceiveEvent(UInt32 input){
simpleLock.lock();
if (Find(stuff, input) != stuff.end()){
RegisterBlock(input));
//dostuff
}
simpleLock.simpleLock.unlock();
}
};
答案 0 :(得分:5)
正在发生的是创建一个线程
std::thread removalCallBack([&](UInt32 input){
std::this_thread::sleep_for(std::chrono::milliseconds(200));
simpleLock.lock();
...
removalCallBack.detach();
然后由于 removalCallBack 是函数 RegisterBlock 的局部变量,当函数退出时,调用 removalCallBack 的析构函数,调用 std :: terminate()
Documentation for thread destructor
〜螺纹(); (自C ++ 11起)
销毁线程对象。如果*仍然有一个关联的运行线程(即joinable()== true),则调用std :: terminate()。
但是根据时间安排,当线程退出时, simpleLock 仍然由线程拥有(忙),根据规范导致未定义的行为,在您的情况下在忙碌时被破坏错误。
要避免此错误,您应该在函数退出后允许线程存在(例如,不使其成为局部变量)或阻塞,直到线程退出,然后使用 thread :: join退出函数 强>
在线程处理之后处理清理可能会非常棘手,特别是如果它们主要用作占用相同地址空间的不同程序,并且在这些情况下很多次会创建一个与您想到的 manager 线程一样其唯一的工作是收回与线程相关的资源。由于 removalCallBack 创建的线程中的工作非常简单,您的情况会更容易一些,但仍有待清理。
如果线程对象将由new创建,那么虽然C ++线程对象表示的系统线程使用的系统资源将被清除,但是对象使用的内存将保持分配,直到调用delete。
另外,考虑一下在线程运行时程序是否退出,然后线程将被终止,但如果在发生这种情况时锁定了互斥锁,则会再次出现未定义的行为。
通常用来保证线程不再运行的是加入它,但是this没有说,pthread_join手册页说明了
一旦线程被分离,它就不能与pthread_join(3)连接或再次成为可连接的。