Other than stopping a program execution with Crtl-C, it is more effective to be able to stop in a concrete line of code. In order to achieve this, a breakpoint needs to be inserted in the code. A breakpoint is a mark the debugger keeps in the code. Whenever the execution reaches a breakpoint, it is suspended and control is taken by the debugger command interpreter. The command to insert a breakpoint is break (or abbreviated as b) followed by the code line to be inserted.
(gdb) l 41 36 37 int main(int argc, char **argv) 38 { 39 unit_ptr buf; 40 41 buf = (unit_ptr)calloc(SIZE, sizeof(struct data_unit)); 42 function(buf); 43 if (check(buf)) 44 { (gdb) b 41 Breakpoint 1 at 0x8048471: file gdb_use.c, line 41. (gdb)
The user may introduce as many breakpoints as needed in different locations in the code. The debugger assigns an integer to each of them as the breakpoint id starting at 1. In the last line of the previous message it can be seen how the introduced breakpoint on line 41 of file gdb_use.c has been assigned the id 1.
The info breakpoints command (or its abbreviation info b) shows the breakpoint list present in the debugger.
(gdb) l 42 37 int main(int argc, char **argv) 38 { 39 unit_ptr buf; 40 41 buf = (unit_ptr)calloc(SIZE, sizeof(struct data_unit)); 42 function(buf); 43 if (check(buf)) 44 { 45 printf("Error detectado en tabla\n"); (gdb) b 42 Breakpoint 2 at 0x8048486: file gdb_use.c, line 42. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x08048471 in main at gdb_use.c:41 2 breakpoint keep y 0x08048486 in main at gdb_use.c:42 (gdb)
Breakpoints can be added at any point in the process execution. Once set, if execution starts with the run (or its abbreviated form r), it stops whenever the first line of code with a breakpoint is reached.
(gdb) r
Starting program: /home/test/gdb_use
Breakpoint 1, main (argc=1, argv=0xfefff604) at gdb_use.c:41
41 buf = (unit_ptr)calloc(SIZE, sizeof(struct data_unit));
(gdb)
Breakpoints can also be inserted using a function name instead of a code line number. In this case, execution is suspended just before the first line of code of such function.
(gdb) b check Breakpoint 3 at 0x80483ce: file gdb_use.c, line 27. (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/test/gdb_use Breakpoint 1, main (argc=1, argv=0xfefff604) at gdb_use.c:41 41 buf = (unit_ptr)calloc(SIZE, sizeof(struct data_unit)); (gdb) c Continuing. Breakpoint 2, main (argc=1, argv=0xfefff604) at gdb_use.c:42 42 function(buf); (gdb) c Continuing. Breakpoint 3, check (table=0x804a008) at gdb_use.c:27 27 for (y = 0; y < SIZE; y++) { (gdb)
As it can be seen in the previous listing, the debugger
suspended the execution when breakpoint number 1 has been reached. After
typing the continue command, execution has proceeded
until breakpoint number 2. The continue command is
introduced again and execution proceeds until the first line of function
check
. The tool shows the line of code about to be executed as
well as the parameter values with which the function has been invoked. Very
often, this information is crucial to diagnose an execution error. The
where command also shows this information but for all
functions that are currently executing.
Each breakpoint can be temporarily disabled/enabled independently. Commands enable and disable followed by the breakpoint number achieve these respectively.
There are three possible commands to continue the program execution. The first one, continue (or c) has already been covered. Execution is continued until the next breakpoint is reached, an error occurs or the execution is interrupted. The second command is next (or its abbreviation n). This command executes one single line of code and suspends again the execution.
(gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/test/gdb_use Breakpoint 1, main (argc=1, argv=0xfefff604) at gdb_use.c:41 41 buf = (unit_ptr)calloc(SIZE, sizeof(struct data_unit)); (gdb) n Breakpoint 2, main (argc=1, argv=0xfefff604) at gdb_use.c:42 42 function(buf); (gdb) n 43 if (check(buf)) { (gdb)
If the line of code executed through the next command contains a function invocation, the debugger suspends the execution after the function has completed. Therefore, this command does not allow to enter in the function and suspend again the execution. The step (or its abbreviation s) command does precisely this. If invoked in a line with a function call, instead of finishing the execution, it enters the function and stops before the first line of code.
(gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/test/gdb_use Breakpoint 1, main (argc=1, argv=0xfefff604) at gdb_use.c:41 41 buf = (unit_ptr)calloc(SIZE, sizeof(struct data_unit)); (gdb) n Breakpoint 2, main (argc=1, argv=0xfefff604) at gdb_use.c:42 42 function(buf); (gdb) s function (table=0x804a008) at gdb_use.c:16 16 for (y = 0; y < SIZE - 1; y++) (gdb)
If the debugger is about to execute a line with no function
call, then the effect of the next and
step commands is identical. Using the
where command it can be checked how the program stopped
in the first line of function
, itself invoked from
main
.
(gdb) where
#0 function (table=0x804a008) at gdb_use.c:16
#1 0x08048491 in main (argc=1, argv=0xfefff604) at gdb_use.c:42
(gdb)