为什么程序在堆栈展开后无法到达正确的 return 指令?
Why program cannot reach proper return instruction after stack unwinding?
编译器:g++ 9.2.0
操作系统:Windows 10
g++ 调用:
g++ -E main.cpp -v -o main.i
g++ -c main.cpp -v -o main.o
g++ main.o -v -o main.exe
main.exe
main.cpp:
#include <chrono>
#include <iostream>
#include <string>
#include <exception>
#include <iostream>
//#include <thread>
#include "mingw.thread.h"
struct Object{
struct Exception : public std::exception{
std::string error_;
Exception(std::string str){
this->error_ = str;
}
~Exception() {
}
std::string get(){
return error_;
}
};
void DoSomeWork() {
try {
std::thread AnotherTh(&Object::GenerateException ,this);
AnotherTh.detach ();
while(true);
}
catch (...) {
throw ;
}
}
void GenerateException(){
std::this_thread::sleep_for (std::chrono::seconds(5));
throw Object::Exception ("Some error");
}
};
int main(){
try{
Object instance;
std::thread th(&Object::DoSomeWork,std::ref(instance));
th.join ();
}
catch (Object::Exception &ex ) {
std::cout << ex.get ();
}
catch (std::exception &ex ){
std::cout << ex.what ();
}
catch (...){
}
std::cout << "never reach this";
return 0;
}
输出:
terminate called after throwing an instance of 'Object::Exception'
what(): std::exception
我正在启动 主线程 和 新线程 (th) 并等待它,在 th 中 启动 另一个线程 将抛出异常。所以,当它出现时,开始堆栈展开(从 Object::GenerateException 到 Object::DoSomeWork 因为没有更多的调用是 Object::GenerateException 的堆栈)并且管理被传递给 Object::DoSomeWork's try-catch ,main 的 try-catch 调用链与从 main 调用的 Object::DoSomeWork "knows" 相同。
我不明白为什么它不能处理异常并将其传递给 main 的 try-catch。
Why program cannot reach proper return instruction after stack unwinding c++?
因为您的代码创建了多个线程,而您没有在实际抛出异常的线程中捕获异常。即使您调用 std::thread
的 join()
成员函数,异常也不会跨线程传播。
Try blocks 被定义为堆栈的动态构造。 try 块捕获代码抛出的异常,代码通过调用从其内容动态访问。
当你创建一个新线程时,你创建了一个全新的堆栈,它根本不是 try 块的动态上下文的一部分,即使调用 pthread_create
或构造 join-able std::thread()
在里面试试。
要捕获源自线程 X 的异常,您必须在线程 X 中使用 try-catch 子句(例如,围绕线程函数中的所有内容,类似于您已经在 main 中执行的操作)。
有关相关问题,请参阅 How can I propagate exceptions between threads?。
一个例子:
#include <chrono>
#include <iostream>
#include <string>
#include <exception>
#include <iostream>
#include <thread>
struct Object {
void DoSomeWork()
{
std::cout << "DoSomeWork Thread ID: " << std::this_thread::get_id() << std::endl;
try {
std::thread thread(&Object::GenerateException, this);
thread.detach();
while(true);
}
catch (...) {
std::cout << "Caught exception: " << std::this_thread::get_id() << std::endl;
throw ;
}
}
void GenerateException(void)
{
std::cout << "GenerateException Thread ID: " << std::this_thread::get_id() << std::endl;
try {
std::this_thread::sleep_for (std::chrono::seconds(5));
throw std::runtime_error("Some error");
} catch (...) {
std::cout << "Caught exception: " << std::this_thread::get_id() << std::endl;
throw;
}
}
};
int main()
{
std::cout << "Main Thread ID: " << std::this_thread::get_id() << std::endl;
try {
Object instance;
std::thread th(&Object::DoSomeWork,std::ref(instance));
th.join();
}
catch (const std::exception &ex) {
std::cout << ex.what() << std::endl;
std::cout << "Exception caught at: " << std::this_thread::get_id() << std::endl;
}
std::cout << "never reach this" << std::endl;
return 0;
}
输出:
Main Thread ID: 140596684195648
DoSomeWork Thread ID: 140596665124608
GenerateException Thread ID: 140596656670464
Caught exception: 140596656670464
terminate called after throwing an instance of 'std::runtime_error'
what(): Some error
Aborted (core dumped)
... if it terminates by throwing an exception, std::terminate
is called.
如果在线程中抛出未捕获的异常,则程序将被强制终止。
编译器:g++ 9.2.0
操作系统:Windows 10
g++ 调用:
g++ -E main.cpp -v -o main.i
g++ -c main.cpp -v -o main.o
g++ main.o -v -o main.exe
main.exe
main.cpp:
#include <chrono>
#include <iostream>
#include <string>
#include <exception>
#include <iostream>
//#include <thread>
#include "mingw.thread.h"
struct Object{
struct Exception : public std::exception{
std::string error_;
Exception(std::string str){
this->error_ = str;
}
~Exception() {
}
std::string get(){
return error_;
}
};
void DoSomeWork() {
try {
std::thread AnotherTh(&Object::GenerateException ,this);
AnotherTh.detach ();
while(true);
}
catch (...) {
throw ;
}
}
void GenerateException(){
std::this_thread::sleep_for (std::chrono::seconds(5));
throw Object::Exception ("Some error");
}
};
int main(){
try{
Object instance;
std::thread th(&Object::DoSomeWork,std::ref(instance));
th.join ();
}
catch (Object::Exception &ex ) {
std::cout << ex.get ();
}
catch (std::exception &ex ){
std::cout << ex.what ();
}
catch (...){
}
std::cout << "never reach this";
return 0;
}
输出:
terminate called after throwing an instance of 'Object::Exception'
what(): std::exception
我正在启动 主线程 和 新线程 (th) 并等待它,在 th 中 启动 另一个线程 将抛出异常。所以,当它出现时,开始堆栈展开(从 Object::GenerateException 到 Object::DoSomeWork 因为没有更多的调用是 Object::GenerateException 的堆栈)并且管理被传递给 Object::DoSomeWork's try-catch ,main 的 try-catch 调用链与从 main 调用的 Object::DoSomeWork "knows" 相同。
我不明白为什么它不能处理异常并将其传递给 main 的 try-catch。
Why program cannot reach proper return instruction after stack unwinding c++?
因为您的代码创建了多个线程,而您没有在实际抛出异常的线程中捕获异常。即使您调用 std::thread
的 join()
成员函数,异常也不会跨线程传播。
Try blocks 被定义为堆栈的动态构造。 try 块捕获代码抛出的异常,代码通过调用从其内容动态访问。
当你创建一个新线程时,你创建了一个全新的堆栈,它根本不是 try 块的动态上下文的一部分,即使调用 pthread_create
或构造 join-able std::thread()
在里面试试。
要捕获源自线程 X 的异常,您必须在线程 X 中使用 try-catch 子句(例如,围绕线程函数中的所有内容,类似于您已经在 main 中执行的操作)。
有关相关问题,请参阅 How can I propagate exceptions between threads?。
一个例子:
#include <chrono>
#include <iostream>
#include <string>
#include <exception>
#include <iostream>
#include <thread>
struct Object {
void DoSomeWork()
{
std::cout << "DoSomeWork Thread ID: " << std::this_thread::get_id() << std::endl;
try {
std::thread thread(&Object::GenerateException, this);
thread.detach();
while(true);
}
catch (...) {
std::cout << "Caught exception: " << std::this_thread::get_id() << std::endl;
throw ;
}
}
void GenerateException(void)
{
std::cout << "GenerateException Thread ID: " << std::this_thread::get_id() << std::endl;
try {
std::this_thread::sleep_for (std::chrono::seconds(5));
throw std::runtime_error("Some error");
} catch (...) {
std::cout << "Caught exception: " << std::this_thread::get_id() << std::endl;
throw;
}
}
};
int main()
{
std::cout << "Main Thread ID: " << std::this_thread::get_id() << std::endl;
try {
Object instance;
std::thread th(&Object::DoSomeWork,std::ref(instance));
th.join();
}
catch (const std::exception &ex) {
std::cout << ex.what() << std::endl;
std::cout << "Exception caught at: " << std::this_thread::get_id() << std::endl;
}
std::cout << "never reach this" << std::endl;
return 0;
}
输出:
Main Thread ID: 140596684195648
DoSomeWork Thread ID: 140596665124608
GenerateException Thread ID: 140596656670464
Caught exception: 140596656670464
terminate called after throwing an instance of 'std::runtime_error'
what(): Some error
Aborted (core dumped)
... if it terminates by throwing an exception,
std::terminate
is called.
如果在线程中抛出未捕获的异常,则程序将被强制终止。