How to set breakpoint in catch block? (c++) - c++

There is something strange happening when I try to debug application. Simply the debugger does not stop on breakpoints when I set breakpoints in catch portion of try-catch block.
Here is an example.
try {
throw std::overflow_error("test");
} catch (...) {
qDebug() << "caught"; // HERE, I SET BREAKPOINT ON THIS LINE
}
It prints the "caught" on screen when exception occurs but it does not stop on this line. (If you ever wonder; Yes, I'm building app in Debug mode and running in Debug mode)
Am I suffering from lack of fundamental knowledge about how gdb works? (I mean maybe it does not stop because breakpoints in catch portion does not work)
Any help would be greatly appreciated.
Thanks.

To catch an exception in IDE, you need issue gdb commands directly in gdb console.
Here's link how to get into gdb console in Qt Create IDE:
Accessing gdb console in Qt-Creator
Once you're the type
catch throw
to stop when your program throws an exception or
catch catch
to stop in the catch block.
If you need to catch a specific library exception, read this thread: GDB: How to break when a specific exception type is thrown?

for people using LLDB,
# set on both throw and catch
breakpoint set -E C++ -h true
# or on catch
b __cxa_begin_catch
# or on throw
b __cxa_throw
while will set breakpoints on throw and catch.

#ben sen, I guess any opinization may result in such a behavior. There are many ways how those options can be specified (via environment variables aka CFLAGS or via IDE options to the project), but they all result to some particular -O option given to the compiller command line. Even if nothing is given at all, please check what is the default optimization for your compiller. My proposal would be to explicitely give -O0 to the compiller and check that no other -O options are supplied.

Related

Program execution continues after procdump created a dump on an exception

I am throwing an exception throw std::exception("dummy") (as a test) which is not being caught anywhere.
Without ProcDump attached this immediately crashes the process as it should.
When I attach ProcDump with -e to a debug build, ProcDump properly detects the unhandled exception, creates a crash dump, and exits.
But the program continues executing as if the exception has never been thrown.
I could manually crash the process after ProcDump exits but I really don't like the idea that code continues to run after a crash that is supposed to be fatal even if it is just for a few ms.
What causes this? How can I make sure that my program crashes (and the crash dump properly represents the point of the crash)? Is this an issue with ProcDump or with how I am using it?
Here is a minimal example to reproduce this:
#include <iostream>
int main() {
char c;
std::cin >> c;
if (c == 'e')
throw std::exception("dummy");
std::cout << "clean exit" << std::endl;
return 0;
}
I've tried it with m$ clang-cl and msvc. I've tried every single ProcDump switch even vaguely relevant to my issue in all possible combinations with multiple binaries.
I don't have a good answer, unfortunately. It looks that there is a bug in procdump. You may report it on the Sysinternals forum or contact Mark Russinovich (#markrussinovich) or Andrew Richards (#arichardmsft). I can confirm that it happens when you attach to the process, for example, procdump -e prog. It behaves as expected when you run the app under procdump (procdump.exe -e -x . prog.exe). Procdump runs as a debugger attached to a process, so it might 'swallow' exceptions. Of course, it should not, but the API allows it to do so.
As an alternative, before procdump gets fixed, you may consider using minidumper (I contributed to it in the past). It does not have as many command-line options as procdump, but the -e option works as expected, for example, MiniDumper.exe -ma -e2 12824.
Internally, minidumper has a very similar design to procdump and also implements a debugger engine. Here is the line handling the exception event:
https://github.com/goldshtn/minidumper/blob/master/MiniDumper/Debugger.cs#L106.
Try using the -k option on ProcDump.

How to get CLion to show exceptions?

I have CLion installed with presumably default configuration. I think something is wrong with it, because I can't see exceptions. For example, this code:
int main(){ throw 5; }
Prints only Process finished with exit code 0
Why doesn't it print the exception?
Why does it print 0 instead of 1?
For comparison:
int main(){try { throw 5; } catch(int x) { std::cout << x << '\n'; }}
This prints 5, so it looks like code is correctly run and the exception is correctly thrown. It's just hidden by CLion somehow.
Edit: This is not a duplicate of "not seeing any console output". I made extremely clear in my question that I was indeed seeing console output for prints. My issue concerns exceptions specifically, not console output generally.
In your first piece of code you have not caught the exception, so it is handled by the default handler. You therefore have no control over the return code from the executable. Operation is as expected.
If you would like CLion to display the exception you can configure it to do so. Note that this will only apply when CLion is debugging your executable, outside of CLion your executable will continue to behave as you have already seen.
Go to run then view breakpoints.
Go to exception breakpoints and when any is thrown.
To display the stack trace when the exception is thrown check stack trace
If you would like your program to stop for your intervention, check enabled and when thrown.
Make sure to use Run/Debug and not Run/Run to launch your program.

Xcode All Exceptions Breakpoint - Ignore Certain C++ Exception

I'm coding in C++ for iOS, using certain iOS Frameworks like AVAudioPlayer. I know that these can trigger C++ exceptions internally and it's perfectly fine, since they catch and handle them.
I would like to use the All Exceptions Breakpoint in Xcode to break on Crash-Issues in my own C++ code, but to ignore that AVAudioPlayer's C++ exceptions (and basically all other catched exceptions).
How can I achieve that?
There isn't a way to do this using the Xcode breakpoint settings.
You can do this in lldb using a Python breakpoint command on the C++ exception breakpoint. Your callback would look up the stack to the point where the exception is thrown, and check that the throwing code is in your shared library, and auto-continue from the breakpoint or not.
The section in:
http://lldb.llvm.org/python-reference.html
on running a script when a breakpoint is hit will give you some details about how to do this.
For instance, you could put:
module_name = "TheNameOfYourExecutableOrSharedLibrary"
def bkpt_cmd (frame, loc, dict):
global module_name
thread = frame.GetThread()
frame_1 = thread.GetFrameAtIndex(1)
module = frame_1.GetModule()
name = module.GetFileSpec().GetFilename()
if module_name in name:
return True
return False
in a file called ~/bkpt_cmd.py. Then in the lldb console, do:
(lldb) br s -E c++
Breakpoint 1: no locations (pending).
(lldb) command script import ~/bkpt_cmd.py
(lldb) br com add -F bkpt_cmd.bkpt_cmd
This will set a C++ exception breakpoint that only triggers when the raising frame is in the shared library called "TheNameOfYourExecutableOrSharedLibrary"...
BTW, if you put the following def in your .py file:
def __lldb_init_module(debugger, internal_dict):
it will get run when the command script import command is executed, so you could use this to add the breakpoint and the command to the breakpoint at one go. I'll leave that as an exercise for the reader.
Note also, this will work when running lldb within Xcode, but you'll want to make your own exception breakpoint as shown above, since Xcode has a different way of handling the commands for the breakpoints it manages.

gdb - Prevent losing backtrace in a catch/rethrow situation

Is it possible to re-throw an exception without losing the back-trace in gdb? Or is there a way in gdb to "back up' a few lines and back trace from there? I'm on GDB 7.7.1, the most recent.
I sometimes find myself running into situations like this, needing a back trace from the original throw of the exception, and needing to comment out the try/catch parts, recompiling, and re-running in gdb.
try {
someFuncThatCanThrowException();
} catch(exceptionType& exception) {
if(#CAN_RECOVER#) {
...
} else {
throw;
}
}
----OR----
try {
someFuncThatCanThrowException();
} catch(exceptionType& exception) {
exception.printMessageToCout();
throw;
}
needing a back trace from the original throw of the exception,
Is it OK to use a simple approach of printing all backtraces of all throws and then when it is necessary to find a backtrace of a particular exception just find it by the address of the exception. Something like this sequence of gdb commands:
set pagination off
catch throw
commands
info args
bt
c
end
When you need to find backtrace of an exception, first print its address, like this:
print &exception
And find its address in the gdb output. It must be printed by info args. As soon as you find address there will be backtrace of this exception after info args output.

How to break when a specific exception type is thrown in GDB?

According to the documentation I can break on specific exception type by using conditional breakpoints. However the syntax for the condition isn't very clear to me:
condition bnum <expression>
Looking at the expression syntax I think this is the pattern I need:
{type} addr
However, I don't know what I should pass for the addr argument. I tried the following:
(gdb) catch throw
(gdb) condition 1 boost::bad_function_call *
But it doesn't work (gdb breaks on all exception types).
Can anyone help?
Update
I also tried #Adam's suggestion, but it results in an error message:
(gdb) catch throw boost::bad_function_call
Junk at end of arguments.
Without boost:: namespace:
(gdb) catch throw bad_function_call
Junk at end of arguments.
Workaround
Breaking in the constructor of bad_function_call works.
EDIT
The documentation suggests that catch throw <exceptname> can be used to break whenever an exception of type <exceptname> is thrown; however, that doesn't seem to work in practice.
(gdb) help catch
Set catchpoints to catch events.
Raised signals may be caught:
catch signal - all signals
catch signal <signame> - a particular signal
Raised exceptions may be caught:
catch throw - all exceptions, when thrown
catch throw <exceptname> - a particular exception, when thrown
catch catch - all exceptions, when caught
catch catch <exceptname> - a particular exception, when caught
Thread or process events may be caught:
catch thread_start - any threads, just after creation
catch thread_exit - any threads, just before expiration
catch thread_join - any threads, just after joins
Process events may be caught:
catch start - any processes, just after creation
catch exit - any processes, just before expiration
catch fork - calls to fork()
catch vfork - calls to vfork()
catch exec - calls to exec()
Dynamically-linked library events may be caught:
catch load - loads of any library
catch load <libname> - loads of a particular library
catch unload - unloads of any library
catch unload <libname> - unloads of a particular library
The act of your program's execution stopping may also be caught:
catch stop
C++ exceptions may be caught:
catch throw - all exceptions, when thrown
catch catch - all exceptions, when caught
Ada exceptions may be caught:
catch exception - all exceptions, when raised
catch exception <name> - a particular exception, when raised
catch exception unhandled - all unhandled exceptions, when raised
catch assert - all failed assertions, when raised
Do "help set follow-fork-mode" for info on debugging your program
after a fork or vfork is caught.
Do "help breakpoints" for info on other commands dealing with breakpoints.
When gdb command 'catch throw' fails, try this workaround :
(tested with Linux g++ 4.4.5/gdb 6.6)
1/ Add this code anywhere in the program to debug :
#include <stdexcept>
#include <exception>
#include <typeinfo>
struct __cxa_exception {
std::type_info *inf;
};
struct __cxa_eh_globals {
__cxa_exception *exc;
};
extern "C" __cxa_eh_globals* __cxa_get_globals();
const char* what_exc() {
__cxa_eh_globals* eh = __cxa_get_globals();
if (eh && eh->exc && eh->exc->inf)
return eh->exc->inf->name();
return NULL;
}
2/ In gdb you will then be able to filter exceptions with :
(gdb) break __cxa_begin_catch
(gdb) cond N (what_exc()?strstr(what_exc(),"exception_name"):0!=0)
where N is the breakpoint number, and exception_name is the name of exception for which we wish to break.
From what I have understood from the question here, you want to break when a specific exception boost::bad_function_call is thrown in your application.
$> gdb /path/to/binary
(gdb) break boost::bad_function_call::bad_function_call()
(gdb) run --some-cli-options
So when the temporary object boost::bad_function_call is constructed in preparation for the throw; gdb will break out!
I have tested this and it does work. If you precisely know the way the exception object is being constructed then you can set breakpoint on the specific constructor, otherwise as shown in the example below, you can omit the arguments prototype list, and gdb will set break points on all different flavours of the constructor.
$ gdb /path/to/binary
(gdb) break boost::bad_function_call::bad_function_call
Breakpoint 1 at 0x850f7bf: boost::bad_function_call::bad_function_call. (4 locations)
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
1.1 y 0x0850f7bf in boost::bad_function_call::bad_function_call() at /usr/include/boost/function/function_base.hpp:742
1.2 y 0x0850fdd5 in boost::bad_function_call::bad_function_call(boost::bad_function_call const&) at /usr/include/boost/function/function_base.hpp:739
1.3 y 0x0863b7d2 <boost::bad_function_call::bad_function_call()+4>
1.4 y 0x086490ee <boost::bad_function_call::bad_function_call(boost::bad_function_call const&)+6>
Another approach is to rely on the tinfo argument available when the catch point is triggered, which is a pointer to the object returned by typeid(type).
So say if I want to catch exception std::bad_alloc being thrown, I could just do:
> p &typeid(std::bad_alloc)
> $1 = (__cxxabiv1::__si_class_type_info *) 0x8c6db60 <typeinfo for std::bad_alloc>
> catch throw if tinfo == 0x8c6db60
Let's assume you have the following code.cpp with a thread that throws an exception:
#include <iostream>
#include <thread>
void thr()
{
while (true) {
new int[1000000000000ul];
}
}
int main(int argc, char* argv[]) {
std::thread t(thr);
t.join();
std::cout << "Hello, World!" << std::endl;
return 0;
}
Compile it with using the following CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(tutorial)
set(CMAKE_CXX_STANDARD 11)
add_executable(test_exceptions main.cpp)
target_link_libraries(test stdc++ pthread)
Now you can play with, running it will give you an abort because of bad_alloc.
Before going on, it's better if you install libstd debug symbols, sudo apt-get install libstdc++6-5-dbg or whatever version you have.
Debug compilation
If you are compiling in Debug you can follow this answer https://stackoverflow.com/a/12434170/5639395 because constructors are usually defined.
Release compilation
If you are compiling in DebWithRelInfo you may not be able to find a proper constructor where to put your breakpoint because of the compiler optimization. In this case, you have some other options. Let's continue.
Source code change solution
If you can change the source code easily, this will work https://stackoverflow.com/a/9363680/5639395
Gdb catch throw easy solution
If you don't want to change the code, you can try to see if catch throw bad_alloc or in general catch throw exception_name works.
Gdb catch throw workaround
I will build on top of this answer https://stackoverflow.com/a/6849989/5639395
We will add a breakpoint in gdb in the function __cxxabiv1::__cxa_throw . This function takes a parameter called tinfo that has the information we need to conditionally check for the exception we care about.
We want something like catch throw if exception==bad_alloc, so how to find the proper comparison?
It turns out that tinfo is a pointer to a structure that has a variable called __name inside. This variable has a string with the mangled name of the exception type.
So we can do something like: catch throw if tinfo->__name == mangled_exception_name
We are almost there!
We need a way to do string comparison, and it turns out gdb has a built-in function $_streq(str1,str2) that does exactly what we need.
The mangled name of the exception is a little harder to find, but you can try to guess it or check the Appendix of this answer. Let's assume for now it is "St9bad_alloc".
The final instruction is:
catch throw if $_streq(tinfo->__name , "St9bad_alloc")
or equivalent
break __cxxabiv1::__cxa_throw if $_streq(tinfo->__name , "St9bad_alloc")
How to find the name of your exception
You have two options
Look for the symbol in the library
Assuming that you installed the libstd debug symbols, you can find the library name like this:
apt search libstd | grep dbg | grep installed
The name is something like this libstdc++6-5-dbg
Now check the files installed:
dpkg -L libstdc++6-5-dbg
Look for something that has a debug in the path, and a .so extension. In my pc I have /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6.0.21.
Finally, look for the exception you want in there.
nm /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6.0.21 | grep -i bad_alloc
Or
nm /usr/lib/x86_64-linux-gnu/debug/libstdc++.so.6.0.21 | grep -i runtime_error
etc.
In my case I found something like 00000000003a4b20 V _ZTISt9bad_alloc which suggested me to use "St9bad_alloc" as the name.
Throw it in gdb and inspect the name in there
This is easy, just start gdb, catch throw everything and run the small executable I wrote before. When you are inside gdb, you can issue a p *tinfo and look for the __name description from gdb.
gdb -ex 'file test_exceptions' -ex 'catch throw' -ex 'run'
(gdb) p *tinfo
$1 = {_vptr.type_info = 0x406260 <vtable for __cxxabiv1::__si_class_type_info+16>,
__name = 0x7ffff7b8ae78 <typeinfo name for std::bad_alloc> "St9bad_alloc"}
As others already mentioned this functionality doesn't work in practice. But as workaround you can put condition on catch throw. When exception is thrown we come to __cxa_throw function. It has several parameters pointing to exception class, so we can set condition on one of them. In the sample gdb session below, I put condition on dest parameter of __cxa_throw. The only problem is that value of dest (0x80486ec in this case) is unknown in advance. It can be known, for example, by first running gdb without condition on breakpoint.
[root#localhost ~]#
[root#localhost ~]# gdb ./a.out
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/a.out...done.
(gdb) catch throw
Catchpoint 1 (throw)
(gdb) condition 1 dest==0x80486ec
No symbol "dest" in current context.
(gdb) r
warning: failed to reevaluate condition for breakpoint 1: No symbol "dest" in current context.
warning: failed to reevaluate condition for breakpoint 1: No symbol "dest" in current context.
warning: failed to reevaluate condition for breakpoint 1: No symbol "dest" in current context.
Catchpoint 1 (exception thrown), __cxxabiv1::__cxa_throw (obj=0x804a080, tinfo=0x8049ca0, dest=0x80486ec <_ZNSt13runtime_errorD1Ev#plt>) at ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc:68
68 ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc: No such file or directory.
in ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc
(gdb) bt
#0 __cxxabiv1::__cxa_throw (obj=0x804a080, tinfo=0x8049ca0, dest=0x80486ec <_ZNSt13runtime_errorD1Ev#plt>) at ../../../../gcc-4.4.3/libstdc++-v3/libsupc++/eh_throw.cc:68
#1 0x08048940 in main () at test.cpp:14
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x008d9ddb exception throw
stop only if dest==0x80486ec
breakpoint already hit 1 time
(gdb)
Update
You must also load debug info for libstdc++ for this workaround to work.
I'm not sure if this is a recent fix, but with GDB GNU gdb (Debian 9.1-2) 9.1, I have used catch throw std::logical_error successfully. I would hate to generalise prematurely, but it is possible this now works correctly in GDB (April 2020).
I think I can answer the part about setting conditional breaks. I won't answer question regarding exceptions as __raise_exception seems to not exist in g++ 4.5.2 (?)
Let's assume that you have following code (I use void to get something similar to __raise_exception from gdb doc)
void foo(void* x) {
}
int main() {
foo((void*)1);
foo((void*)2);
}
to break at foo(2) you use following commands
(gdb) break foo
Breakpoint 1 at 0x804851c: file q.cpp, line 20.
(gdb) condition 1 x == 2
If you run with
(gdb) r
you will see that it stops on the second foo call, but not on the first one
I think, what they meant in docs is that you set break on function __raise_exception (very implementation dependent)
/* addr is where the exception identifier is stored
id is the exception identifier. */
void __raise_exception (void **addr, void *id);
and then set conditional break on id as described above (you have to somehow determine what is id for yours exception type).
Unfortunately
(gdb) break __raise_exception
results with (g++ 4.5.2)
Function "__raise_exception" not defined.
In case the problem is that there is no valid stack trace (not breaking in raise), it seems to be a problem when re-compiling without re-starting gdb.
( i.e. calling "make" inside the gdb console).
After having re-started gdb, it breaks correctly in raise.c
(my versions : GNU gdb 8.1.0.20180409-git, gcc 7.4.0, GNU make 4.1)