Once of the cool things about debugging with IDEs is that they typically give you a nice mechanism to watch the changing state of variables as you step through code. In Visual Studio, for example, you can right click on a variable name and select “Add Watch” from the menu. The variable name and its current value will be shown in a little “Watch” window. You can watch as many variables as you have the resources and patience for. As you step through the code, anytime the value of a watched variable changes, that change is reflected in the Watch window.
Can we do something similar in gdb? Absolutely.
The command we’re interested in is display. When gdb is told to display a variable, it’ll report that variable’s current value every time program execution pauses (e.g., stepping through the code).
Let’s see an example using the following snippet of code.
// demo.cpp int main() { int a = 1; int b = 2; int c = 3; a = a + 1; b += a; c = a * b + c; return 0; } |
First we compile and then launch gdb.
skirk@dormouse:~$ g++ -g ./demo.cpp -o demo skirk@dormouse:~$ gdb ./demo GNU gdb (GDB) 8.0.1 Copyright (C) 2017 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 "x86_64-pc-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /home/skirk/demo...done. (gdb) |
Let’s now run our app, stopping at main().
(gdb) start Temporary breakpoint 1 at 0x4004bb: file ./demo.cpp, line 3. Starting program: /home/skirk/demo Temporary breakpoint 1, main () at ./demo.cpp:3 3 int a = 1; |
Let’s say at this point we want to display the values of variables a, b, and c as we step through the code. We can issue the display command like so.
(gdb) display a 1: a = 32767 (gdb) display b 2: b = 0 (gdb) display c 3: c = 0 |
After each display is executed, gdb shows the current value for the variable specified. In this example, our variables have bogus values because they haven’t been initialized yet. Let’s now step through the code and see what display does for us.
(gdb) n 4 int b = 2; 1: a = 1 2: b = 0 3: c = 0 (gdb) n 5 int c = 3; 1: a = 1 2: b = 2 3: c = 0 (gdb) n 7 a = a + 1; 1: a = 1 2: b = 2 3: c = 3 (gdb) n 8 b += a; 1: a = 2 2: b = 2 3: c = 3 (gdb) n 9 c = a * b + c; 1: a = 2 2: b = 4 3: c = 3 (gdb) n 11 return 0; 1: a = 2 2: b = 4 3: c = 11 |
Every time we step through the code, our program execution pauses and the current values of the variables we asked gdb to display are shown. As you can imagine, this can save a tremendous amount of time over, say, repeatedly using a step command followed by a print command.
It’s worth noting that the variable value information will only be displayed for variables that are currently in scope. If the variables we’re interested in are local to a function that at some point returns, those variables will no longer be displayed once they’re out of scope. However, gdb doesn’t forget about those variables. It will absolutely display them the next chance it gets. If you later step into that function again, those variables will be displayed.
When you’re no longer interested in a given variable, you can issue the undisplay command. The gotcha here is that undisplay doesn’t operate on variable names. It operates on display numbers. “Where is the display number?” you ask. It’s the number next to the “variable=value” line in the display output. In our example above, the display output for our variable c is “3: c = 11”. Note the 3 before the colon? It’s not just to pretty up the output. That’s the display number assigned to that particular variable.
You can undisplay a single display number like so.
(gdb) undisplay 1 |
You can also undisplay multiple display numbers at once.
(gdb) undisplay 2 3 |
Note that the display command shouldn’t be confused with the watch command, which serves a related purpose. The watch command works more like a smart breakpoint (these are actually called watchpoints) in that it stops program execution and displays a given variable’s value only when the value changes. The display command provides a continuous display of variables and doesn’t affect program execution at all.