On Linux, I would like to be able to determine whether a catch block for a particular class of exception (or a superclass of that class) is currently in scope (ignoring catch all blocks).
In particular, I would like to be able to implement the isThereACatchBlock function to behave as follows:
bool isThereACatchBlock( std::type_info const & ti ) {
...;
}
class MyException {
};
class MyDerivedException : public MyException {
};
class MyOtherException {
};
void f() {
try {
isThereACatchBlock( typeid( MyException ) ); // Should return true
isThereACatchBlock( typeid( MyDerivedException ) ); // Should return true
isThereACatchBlock( typeid( MyOtherException ) ); // Should return false
} catch( MyException const & e ) {
} catch( ... ) {
}
}
I know that the system has this information, in order that it can implement exception handling correctly -- I believe it's stored in the .eh_frame and/or .gcc_except_table sections, as described in this post. However, I'm not sure if there is any easy(-ish) way for a program to interpret that information. Can anyone help?
Reading one of your comments, I saw that one reason you want to do this is to avoid generating a backtrace for handled exceptions, but unhandled exceptions, you want to have the backtrace.
If that's why you want to do this, you can use std::set_terminate() to set up a termination handler, which is called when an unhandled exception occurs. Testing with my own backtrace handler, the backtrace shows trace all the way up to the throw() that caused the failure, since the throw basically calls the terminate handler directly, after it realizes the exception is not going to be caught.
Note, this only captures the stack from the most recent throw until it's terminated. If you catch and then rethrow the exception, the stack between the initial throw and the catch is unwound and no longer available.
int foo() {
throw std::runtime_error("My error");
}
std::terminate_handler old_term_func;
void term_func() {
// Insert backtrace generation/output here
old_term_func();
}
void test() {
try {
foo();
} catch (const std::runtime_error& e) {
std::cout <<"Exception caught, no backtrace generated" << std::endl;
}
foo(); // Exception not caught, will call term_func
}
int main() {
old_term_func = std::set_terminate( term_func ) ;
test();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With