Debugging tools typically offer a variety of mechanisms with which to set breakpoints.
You've learned that GDB gives the illusion of running a program line by line of source code. You've also learned that in order to do anything really useful with GDB you need to instruct it where to pause execution so you can perform debugging activitites with GDB's command-line prompt. In this section, you'll learn how to set breakpoints, which tell GDB where to stop within your source code.
There are many different ways to specify a breakpoint in GDB; here are some of the most common methods:
break function
Set a breakpoint at the entry (first executable line) of the function function()
. You saw an example of this in Breakpoint Lists in GDB; the command
(gdb) break main
sets a breakpoint at the entry of main()
.
break line_number
Set a breakpoint at line line_number
of the currently active source code file. For multi-file programs, this is either the file whose contents you last looked at using the list
command or the file containing main()
. You saw an example of this in Overview of Breakpoints;
(gdb) break 35
which set a breakpoint at line 35 in file bed.c.
break filename:line_number
Set a breakpoint at line line_number
of the source code file filename
. If filename
isn't in your current working directory, you can give a relative or full pathname to help GDB find the file, for example:
(gdb) break source/bed.c:35
break filename:function
Set a breakpoint at the entry of function function()
within the file filename
. Using this form may be required for overloaded functions or for programs that use identically named static functions, for example:
(gdb) break bed.c:parseArguments
As we'll see, when a breakpoint is set, it stays in effect until you delete it, disable it, or quit GDB. However, a temporary breakpoint is a breakpoint that is automatically deleted after the first time it's reached. A temporary breakpoint is set with the tbreak
command, which takes the same type of arguments that break
takes. For example, tbreak foo.c:10
sets a temporary breakpoint at line 10 of file foo.c.
A comment needs to be made about functions with the same name. C++ allows you to overload functions (define functions with the same name). Even C allows you to do this if you use the static
qualifier to declare the functions with file scope. Using break
will set a breakpoint at all functions with the same name. If you want to set a breakpoint at a particular instance of the function, you need to be unambiguous, such as by giving the line number within a source code file in your break command.function
The location at which GDB actually sets a breakpoint may be different from where you requested it to be placed. This can be somewhat discon certing for people new to GDB, so let's look at a short example that demonstrates this quirk. Consider the following short program, test1.c:
1 int main(void) 2 { 3 int i; 4 i = 3; 5 6 return 0; 7 }
Compile this program without optimization and try setting a breakpoint at the entry of main()
. You would think that the breakpoint would be placed at the top of the function—either line 1, line 2, or line 3. Those
would be good guesses for the location of the breakpoint, but they're wrong. The breakpoint is actually set at line 4.
$ gcc -g3 -Wall -Wextra -o test1 test1.c $ gdb test1 (gdb) break main Breakpoint 1 at 0x6: file test1.c, line 4.
Line 4 is hardly the first line of main()
, so what happened? As you may have guessed, one issue is that that line is executable. Recall that GDB actually works with machine language instructions, but with the magic of an enhanced symbol table, GDB gives the illusion of working with source code lines. Normally, this fact isn't terribly important, but this is a situation in which it becomes important. Actually, declaring i
does generate machine code, but it is not code that GDB finds useful for our debugging purposes.[3]. Therefore, when you told GDB to break at the start of main()
, it set a breakpoint at line 4.
The problem may become worse when you compile the program with optimizations. Let's take a look. Recompile the program with optimization turned on:
$ gcc -O9 -g3 -Wall -Wextra -o test1 test1.c $ gdb test1 (gdb) break main Breakpoint 1 at 0x3: file test1.c, line 6.
We asked to put a breakpoint at the start of main()
, but GDB placed one on the last line of main()
. Now what happened? The answer is the same as before, but GCC took a more active role. With optimizations turned on, GCC noticed that although i
was assigned a value, it was never used. So in an effort to generate more efficient code, GCC simply optimized lines 3 and 4 out of existence. GCC never generated machine instructions for these lines. Therefore, the first line of source code that generated machine instructions happens to be the last line of main()
. This is one of the reasons you should never optimize code until you're finished debugging it.[4]
The upshot of all this is that if you find that setting a breakpoint doesn't produce a breakpoint exactly where you'd expect it to, you now know why. Don't be surprised.
On a related matter, we'd like to mention what happens when more than one breakpoint lives at the same line of source code. When GDB breaks at a source code line with more than one breakpoint, it will only break there once. In other words, after it hits that line of code, if you resume execution, the other breakpoints which happen to be on the same line will be ignored. In fact, GDB keeps track of which breakpoint "triggered" the program execution to stop. On a line of code with multiple breakpoints, the breakpoint that triggers the break will be the breakpoint with the lowest identifier.
To set breakpoints with DDD, find the line of code at which you want to set the breakpoint in the Source Window. Position the cursor over any empty space on that line and right-click to reveal a pop-up menu. Drag the mouse down until the Set Breakpoint choice is highlighted, and then release the mouse button. You should see a red stop sign next to the line of code where you set the breakpoint. If you are not doing anything special with the breakpoint, such as making it conditional (which will be discussed in Conditional Breakpoints), a shortcut is to simply double-click the given line.
If you've been experimenting with DDD, you may have noticed that when you press the right-hand button next to a line of code, the pop-up menu contains the choice Set Temporary Breakpoint. This is how you set a temporary breakpoint (a breakpoint that disappears after the first time it's reached) with DDD, which invokes GDB's tbreak
command.
Again, don't forget that DDD is really a GDB frontend. You can issue any GDB-style break commands in DDD using DDD's Console Window. Sometimes this is desirable; if you have a very large or a multi-file program, it could be more convenient to issue a breakpoint using GDB semantics. In fact, sometimes it's necessary because not all of GDB's breakpoint commands are invocable from the DDD interface.
To set a breakpoint at a given line in Eclipse, double-click on that line. A breakpoint symbol will appear, as seen, for example, in the line in Figure 2-2.
insert(x[num_y]);
To set a temporary breakpoint, click the line, then right-click in the source window, and select Run to Line. Note, however, that the Run to Line operation only works if the target line is in the same function as your current position, and if you do not exit the function before re-entering and hitting this line.