Reputation: 3598
Is it possible to add a condition to catch throw
to ignore the throw if the call stack contains a certain routine?
Background
Our code has (for better or worse) various locations where it throws an exception. The exception is caught and then the code continues. If I am trying to run until it crashes in the debugger, this means I have to repeated start running the program again.
Example
In the following code, I would like to stop when b()
throws, but not when a()
throws.
void a() {
throw SomeException("a");
}
void b() {
throw DifferentException("b");
}
main(int argc, char** argv) {
for (int index = 0; index < 10; ++index)
try {
a();
} catch (...) {
// Log exception
}
}
b();
}
I would be happen if any of these theoretical commands worked:
catch throw not(SomeException)
catch throw not(stack(a))
It appears that I could say catch throw DifferentException
, but that needs to be customized for however the program is currently failing, while "anything bu SomeException" I could put in my gdbinit file and it would always work without effort.
Upvotes: 2
Views: 599
Reputation: 21
Slightly off-topic, but when the condition may be set on the thrown object type rather than parent method, here is an example, made within gdb 7.6 under netbeans, of a breakpoint on all throws except those that are of type ios_base::failure
(gdb) info br
<snip>
39 breakpoint keep y 0x00002aaaac983580 in __cxxabiv1::__cxa_throw(void*, std::type_info*, void (*)(void*)) at ../../../../gcc-4.4.5-20110214/libstdc++-v3/libsupc++/eh_throw.cc:70
stop only if tinfo != 0x2aaaacbb03f0
breakpoint already hit 1 time
Upvotes: 0
Reputation:
As for this:
catch throw not(stack(a))
This is an example that shows how catch it with gdb 7.6. First, there will be a couple of files test.gdb and test.py:
>cat test.gdb
source test.py
catch throw
command
if $check_a()==1
continue
else
bt
end
end
r
>cat test.py
class check_a (gdb.Function):
def __init__ (self):
super (check_a, self).__init__ ("check_a")
def invoke (self):
if gdb.selected_frame().older().name() == "a":
return 1
else:
return 0
check_a()
And this is test itself:
>gdb -q -x test.gdb ./tt
Reading symbols from /home/tt...done.
Catchpoint 1 (throw)
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400990 <typeinfo for SomeException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400960 <typeinfo for DifferentException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
63 header->unexpectedHandler = __unexpected_handler;
#0 __cxxabiv1::__cxa_throw (obj=0x601080, tinfo=0x400960 <typeinfo for DifferentException>, dest=0x0) at ../../../../gcc-4.3.3/libstdc++-v3/libsupc++/eh_throw.cc:63
#1 0x00000000004007b1 in b () at t.cpp:20
#2 0x0000000000400839 in main (argc=1, argv=0x7fffffffe208) at t.cpp:35
(gdb)
Upvotes: 1
Reputation: 22519
Very recent versions of gdb can examine the type of the exception being thrown. This requires a bit of support in libstdc++ as well... perhaps difficult to set up.
If your gdb has Python scripting enabled (probable) then search for the "$_caller_is" convenience function. This is shipped with Fedora at least. This lets you easily examine the stack from a breakpoint condition, like:
catch throw
break if !$_caller_is('a')
You may need to pass some extra argument to make it search up the stack more than 1 level. Anyway the function is short and readily modified to do whatever you like.
Upvotes: 2