【发布时间】:2018-03-05 20:39:09
【问题描述】:
我有自己的线程类,旨在帮助安全地管理异常。它看起来像这样:(为简单起见,跳过了其他构造函数和互斥体)
class ExceptThread
: public std::thread {
public:
template<typename Func, typename... Args>
ExceptThread(Func&& f, Args&&... args)
: std::thread([] (Args&&... args) {
try {
return f(args...);
} catch(...) {
exc = std::current_exception();
}
}, args...) { }
// skipped other constructors etc.
//...
void check() {
if(exc) {
std::exception_ptr tmp = exc;
exc = nullptr;
std::rethrow_exception(tmp);
}
}
private:
std::exception_ptr exc;
};
这个类的意思是这样使用:
ExceptThread et([] { std::this_thread::sleep_for(5s); throw std::runtime_error("Ugly exception"); });
try {
while(/*...*/) {
// main loop
et.check();
}
} catch(std::exception& e) {
// do sth
}
问题:
当线程抛出异常时,它被catch(...) 捕获并保存到exc,一切都很好。但是当执行更进一步时,std::terminate 会被调用,就像没有捕获到异常一样。我还尝试在捕获异常后暂停子线程(例如Sleep(INFINITE)),但在主线程中的堆栈展开期间在分离std::thread::~thread() 中的线程时调用std::terminate()。如何防止系统这样做?
平台:MSVC
【问题讨论】:
-
线程正常退出时;它不调用 std::terminate。这意味着您的异常处理可能正在抛出......您可能想在调试器中进行调查。
-
您的代码中有一个数据竞争,因为您从新创建的线程中修改了
exc成员变量,并通过check从主线程中读取它成员函数。 -
为了简单起见,我在发布的示例中跳过了同步
标签: c++ multithreading exception-handling