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.
-gto let the compiler construct debug info into the executable.
-ggdb3could make gdb debug macros.
-fno-omit-frame-pointerto keep away from the compiler optimizing out small capabilities, with the intention to see the total name stack.
-0gto 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 with
run 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_fileand 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 pidto 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 funcwill break at a operate.
break instance.cc:10will break at line 10 of the instance.cc, if there is just one file, we are able to omit the filename, simply use
break 10. And we are able to kind
listingto indicate the codes across the present line.
data breakscan present you all breakpoints you will have set.
delete 2will 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 argscan present us the arguments of a operate.
data localscan present us the native variables of the present operate.
print aprints a variable.
print a=2will first consider
a=2after which print the end result. Notice that should you straight kind
a=2, you’re going to get an error.
print sum(1, a)calls the operate
(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 /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
$2, are additionally variables that can be utilized additional.
dprintf locaion, format-string, expr1, expr2.
drpintfis a handy command that may dynamically print on the location, simply as you will have inserted an
printfexpression on the location.
set $foo = 4can set a variable. That is handy if you wish to avoid wasting intermediate outcomes.
command 2is one other gdb command, that you may set instructions to be executed when hit the particular breakpoints. The illustration under will execute
data localsroutinely when the primary breakpoints are hit. You too can use this methodology to attain the identical results of
(gdb) command 1
Kind instructions for breakpoint(s) 1, one per line.
Finish with a line saying simply “finish”.
print *&arr@5can 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.
runwill begin working this system and cease on the first breakpoint, if there aren’t any breakpoints, this system will cease on the exit.
beginwill begin this system and cease the
proceedwill proceed this system and cease on the subsequent breakpoint or exit.
endwill cease when the present operate finishes.
subsequentwill cease on the subsequent line.
stepwill 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.
btwill present the present backtrace.
upwill transfer you to the higher body.
downwill transfer you to the decrease body.
body 2will straight take you to the second body.
When debugging a multithread program,
data threadsreveals all threads.
thread 5will go to the fifth thread.
thread apply all [command]will execute a command on all threads. It’s very handy to make use of
thread apply all bt fullto print all backtrace of all threads.
Gdb has a configuration file, situated at
~/.gitinit or within the present folder, identical to
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 onwill output all output to
gdb.txt. That is helpful when instructions output a lot info, just like the above
thread apply all bt full.
set historical past save onsaves the command historical past.
set pagination offdisable the interactive show of lengthy display output.
set print fairly oncan show a c++ class with a extra fairly format.
set affirm offdisable 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:
listing [folder]so as to add the particular listing to gdb’s search path.
set substitute-path [src] [dst]to substitute path.
You too can develop macro to see the small print after preprocessing.
macro develop some_macro(macro_arg)to develop macro.
data macro some_macroto 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
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.