子进程异常 与 主进程异常
在线程中抛出的异常默认不会自动传递到主线程(或父线程)。如果子线程中未捕获异常,程序会直接终止(调用 std::terminate())。若需在线程间传递异常,需手动捕获并处理。以下是具体分析和解决方案:
1. 默认行为:异常不跨线程传递
问题示例
#include <thread>
#include <iostream>
void thread_func() {
throw std::runtime_error("子线程抛出异常");
}
int main() {
try {
std::thread t(thread_func);
t.join();
} catch (const std::exception& e) {
std::cout << "捕获到异常: " << e.what() << std::endl;
}
return 0;
}
结果:
程序崩溃,调用 std::terminate(),主线程的 catch 块无法捕获子线程的异常。
2. 解决方案:手动捕获并传递异常
方法 1:使用 try-catch 捕获子线程异常
在子线程内部捕获异常,通过共享变量传递错误信息:
#include <thread>
#include <iostream>
#include <exception>
#include <mutex>
std::exception_ptr thread_exception = nullptr;
std::mutex mtx;
void thread_func() {
try {
throw std::runtime_error("子线程抛出异常");
} catch (...) {
std::lock_guard<std::mutex> lock(mtx);
thread_exception = std::current_exception(); // 捕获异常指针
}
}
int main() {
std::thread t(thread_func);
t.join();
if (thread_exception) {
try {
std::rethrow_exception(thread_exception); // 重新抛出异常
} catch (const std::exception& e) {
std::cout << "主线程捕获到异常: " << e.what() << std::endl;
}
}
return 0;
}
输出:
主线程捕获到异常: 子线程抛出异常
方法 2:使用 std::promise 和 std::future
通过 std::promise 存储异常,主线程通过 std::future 获取:
#include <thread>
#include <iostream>
#include <future>
void thread_func(std::promise<void> prom) {
try {
throw std::runtime_error("子线程抛出异常");
} catch (...) {
prom.set_exception(std::current_exception()); // 传递异常到 promise
}
}
int main() {
std::promise<void> prom;
std::future<void> fut = prom.get_future();
std::thread t(thread_func, std::move(prom));
t.detach(); // 或 t.join()
try {
fut.get(); // 触发异常(若子线程有异常)
} catch (const std::exception& e) {
std::cout << "主线程捕获到异常: " << e.what() << std::endl;
}
return 0;
}
输出:
主线程捕获到异常: 子线程抛出异常
3. 最佳实践
- 始终在子线程内部捕获异常
避免未捕获的异常导致程序终止。 - 优先使用
std::promise/future
适用于需要返回值或异常传递的异步任务。 - 对不可恢复的异常直接记录日志
若主线程无法处理子线程的异常(如内存错误),应在子线程中记录日志后退出。

浙公网安备 33010602011771号