Energy up your debugging abilities
The GNU Undertaking debugger (GDB) is a really helpful debugger underneath Linux.
Good programmers often use gdb to debug bugs, when a program core dumps, or a program happens sudden behaviors. On this article, I’ll present you how you can use gdb effectively.
Compilers usually make many optimizations with a view to generate optimum code, which makes debugging troublesome. If you happen to encounter errors like symbols not discovered, you’ll want to open applicable compile flags for debugging, in order that the debugger can get sufficient info.
- use
-g
to let the compiler construct debug info into the executable. - use
-ggdb3
could make gdb debug macros. - use
-fno-omit-frame-pointer
to keep away from the compiler optimizing out small capabilities, with the intention to see the total name stack. - use
-0g
to let the compiler activate optimizations that don’t have an effect on debugging.
After compiling a program with applicable flags, we are able to use GDB to debug the generated executable. There are various totally different eventualities, and the startup methodology in every state of affairs is barely totally different.
- Within the first state of affairs, now we have an executable that accepts some parameters. We will begin gdb with
gdb executable
, after which run this system withrun arg1 arg2
. - Within the second state of affairs, a core dump file is generated when an executable is working, in all probability a section fault. We will begin gdb with
gdb executable coredump_file
and gdb will cease at the place the error occurs. - Within the third state of affairs, now we have an executable that’s working. We will use
gdb connect pid
to connect to the method.

After beginning gdb, we often set a breakpoint. This system will pause when it hits a checkpoint. And we are able to observe the standing of this system.
break func
will break at a operate.break instance.cc:10
will break at line 10 of the instance.cc, if there is just one file, we are able to omit the filename, simply usebreak 10
. And we are able to kindlisting
to indicate the codes across the present line.data breaks
can present you all breakpoints you will have set.delete 2
will delete the second breakpoint.- You too can set conditional breakpoints, simply append
if [condition]
to interrupt command. watch [variable]
can set a watch on a variable, watches are one other type of breakpoint, that can pause this system if the watched variable has modified.

When paused on a breakpoint, we are able to observe the standing of this system by printing variables and expressions.
data args
can present us the arguments of a operate.data locals
can present us the native variables of the present operate.print
can be utilized to indicate the results of a variable or an expression. See the bellow illustrations.print a
prints a variable.print a=2
will first considera=2
after which print the end result. Notice that should you straight kinda=2
, you’re going to get an error.print sum(1, a)
calls the operatesum
.
(gdb) print a
$1 = 1
(gdb) print a=2
$2 = 2
(gdb) print sum(1, a)
You too can format the end result of print
,
print /x <exp>
will present the lead to hexadecimal.print /t <exp>
will present the lead to binary.print /d <exp>
will present the lead to unsigned int format.print /c <exp>
will present the lead to signed int format.- Notice the outcomes of
print
, reminiscent of$1
,$2
, are additionally variables that can be utilized additional. dprintf locaion, format-string, expr1, expr2
.drpintf
is a handy command that may dynamically print on the location, simply as you will have inserted anprintf
expression on the location.set $foo = 4
can set a variable. That is handy if you wish to avoid wasting intermediate outcomes.command 2
is one other gdb command, that you may set instructions to be executed when hit the particular breakpoints. The illustration under will executedata locals
routinely when the primary breakpoints are hit. You too can use this methodology to attain the identical results ofdprintf
.
(gdb) command 1
Kind instructions for breakpoint(s) 1, one per line.
Finish with a line saying simply “finish”.
>data locals
>finish
print *&arr[96]@5
can print the 96–100 components of an array.
Notice at present we cannot simply print std::vector or different c++ stdlib containers. We’ll focus on this matter later.
There are a number of instructions permitting us to manage the execution of this system within the gdb session.
run
will begin working this system and cease on the first breakpoint, if there aren’t any breakpoints, this system will cease on the exit.begin
will begin this system and cease thefundamental
operate.proceed
will proceed this system and cease on the subsequent breakpoint or exit.end
will cease when the present operate finishes.subsequent
will cease on the subsequent line.step
will enter a operate and cease there.
Gdb accommodates a textual content consumer interface (TUI), identical to most IDEs, which might show traces of code whereas debugging. tui allow
to enter the tui mode, and tui disable
to exit.

Backtrace is helpful for debugging, particularly once we debug a core dump.
bt
will present the present backtrace.up
will transfer you to the higher body.down
will transfer you to the decrease body.body 2
will straight take you to the second body.
When debugging a multithread program,
data threads
reveals all threads.thread 5
will go to the fifth thread.thread apply all [command]
will execute a command on all threads. It’s very handy to make use ofthread apply all bt full
to print all backtrace of all threads.
Gdb has a configuration file, situated at ~/.gitinit
or within the present folder, identical to .vimrc
for vim
. The configuration file within the present path has a better precedence to be loaded than ~/.gitinit
. Let’s focus on some configurations.
set logging on
will output all output togdb.txt
. That is helpful when instructions output a lot info, just like the abovethread apply all bt full
.set historical past save on
saves the command historical past.set pagination off
disable the interactive show of lengthy display output.set print fairly on
can show a c++ class with a extra fairly format.set affirm off
disable affirmation.
Since gdb cannot print c++ containers reminiscent of std::vector
conveniently, we are able to write some scripts to make it simple. Follows https://gist.github.com/skyscribe/3978082.
Typically we encounter errors like xxx.c: No such file or listing
. Because of this gdb cannot discover the supply file. The options are:
- use
listing [folder]
so as to add the particular listing to gdb’s search path. - use
set substitute-path [src] [dst]
to substitute path.
You too can develop macro to see the small print after preprocessing.
- use
macro develop some_macro(macro_arg)
to develop macro. - use
data macro some_macro
to see its definition.
Notice gdb will analyze the context of the present operate, solely macros which are seen within the present context will be expanded.
One highly effective command of gdb is document
, which data the state of the working program, and means that you can back-run this system. Gdb additionally gives a bunch of instructions beginning with reverse
prefix, like reverse-continue
, reverse-finish
, reverse-next
, reverse-nexti
, reverse-step
, reverse-stepi
.
One utilization of document
is to seek out reminiscence corruption. You may run this system in gdb, document the execution of this system, and cease on the location the place reminiscence corruption occurred. Then you may watch the reminiscence handle that was corrupted. Then reverse run this system to see the place the content material of the handle has modified.
The disadvantage of document
is that it’ll decelerate your program. It nonetheless takes some work to make use of it nicely.
Typically, you’ll want to regulate the code repeatedly and run this system a number of occasions to progressively perceive the small print of the bug. However should you restart gdb each time, it will likely be inconvenient to set checkpoints repeatedly. We will save the debug session and reload it later.
If you happen to use a makefile to construct your program, you may merely kind make
inside the gdb session, it should rebuild your program and reset the checkpoints.
You too can use save breakpoints bp.txt
to avoid wasting the breakpoints to bp.txt, and use supply bp.txt
to reload these breakpoints later, or use gdb -x bp.txt --args [exe]
to load it when gdb begins.
Along with gdb, there are lots of different debug strategies: reminiscent of analyzing logs. Binary search git commits. They’ve their very own benefits and drawbacks. When debugging a program, you may mix these strategies to resolve the issue effectively. The benefit is that you’ve got full entry to the working program, that is extraordinarily helpful when a bug is difficult to breed.