未运行catch处理程序。但为什么呢?
如果thread t
在try
块之前启动,则捕获处理程序将运行。
如果catch块的类型与抛出的类型不匹配,则程序退出,说明线程以未捕获的异常终止,表明异常已处理,但catch块未运行。
#include <iostream>
#include <thread>
using namespace std;
void do_work() {}
int main() {
std::cerr << "RUNNING" << std::endl;
try {
thread t(do_work);
std::cerr << "THROWING" << std::endl;
throw logic_error("something went wrong");
} catch (logic_error e) {
std::cerr << "GOTCHA" << std::endl;
}
return 0;
}
编译命令:
c++ -std=c++14 -pthread -pedantic -Wall -Wextra -O0 scratch.cpp -o scratch
答案 0 :(得分:5)
你忘了加入主题:
try {
thread t(do_work);
t.join(); // <<< add this
std::cerr << "THROWING" << std::endl;
throw logic_error("something went wrong");
} catch (logic_error e) {
std::cerr << "GOTCHA" << std::endl;
}
A joinable thread that goes out of scope, causes terminate
to be called。因此,您需要在超出范围之前调用join
或detach
。
答案 1 :(得分:2)
在 C ++ 11,30.3.1.3中,线程析构函数标准说
如果是joinable()则终止(),否则没有效果。 [注意:隐式分离或连接其析构函数中的joinable()线程可能导致无法调试正确性(用于分离)或性能(用于连接)仅在引发异常时遇到的错误。因此,程序员必须确保在线程仍可连接时永远不会执行析构函数。 - 后注]
因此,一旦调用了线程析构函数,你的程序terminate
就会因为范围结束而且永远不会执行catch
逻辑。
如果您希望程序从线程范围中捕获异常但在线程仍可连接时抛出,则需要在线程本身的范围内捕获它,join或{{3线程并重新抛出任何被捕获的东西。
try
{
std::thread t(foo);
try
{
std::cerr << "THROWING" << std::endl;
throw std::logic_error("something went wrong");
}
catch (...) // catch everything
{
t.join(); // join thread
throw; // rethrow
}
t.join();
}
catch (std::logic_error & e)
{
std::cerr << "GOTCHA: " << e.what() << std::endl;
}