You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
You thought you were getting a bargain when you bought that pocket watch from that scary old lady at the flea market in the French Quarter.
6
-
Little did you realize that pocket watch did more than just tell time[^tell-time].
6
+
Little did you realize that pocket watch did more than just tell time.[^tell-time]
7
7
In fact, holding the button on the side *slows down* time.
8
8
9
9
At first it's a novelty.
10
10
You prank your roommate.
11
11
Maybe take some extra time on a test.
12
12
Steal a quick bagel for breakfast.
13
-
Rob a bank[^escalation]...
13
+
Rob a bank...[^escalation]
14
14
15
15
It was all fun up to this point.
16
16
But now you're here: standing in front of at an array of red-hot lasers, trapped in the vault of the Big Bank of New York, wondering where it all went wrong, and wearing a fancy turtle neck.
@@ -39,14 +39,14 @@ You cut the wrong blue wire!
39
39
40
40
You reach into your pocket to grab your watch and reset time.
41
41
Instead, you pull out that pastrami sandwich from last lab.
42
-
Also you've turned into a raccoon somehow.
42
+
Also, you've turned into a raccoon somehow.
43
43
44
-
You wake up[^dream].
44
+
You wake up.[^dream]
45
45
46
-
In real life, you may not be able to slow down or reset time analyze disasters in detail[^bank-robber].
46
+
In real life, you may not be able to slow down or reset time to analyze disasters in detail.[^bank-robber]
47
47
You can, however, slow down disasters as they happen in your programs.
48
48
49
-
Using a **debugger** you can slow down the execution of your programs to help you figure out why it's not working.
49
+
Using a **debugger**, you can slow down the execution of your programs to help you figure out why it's not working.
50
50
A debugger can't automatically tell you what's broken, but it can...
51
51
52
52
- step through your code line by line
@@ -59,36 +59,153 @@ In your bank robber dream, the watch allowed you to slow down time to see what s
59
59
In real life, a debugger allows you to slow down the execution of your program, so that you can see where and when it breaks.
60
60
It's still up to you to figure out why it's breaking and how to fix your bugs, but a debugger can definitely give you some clues to make it easier to find them.
61
61
62
-
In this lab, we'll be using the GNU Debugger (`gdb`) to debug a couple of C++ programs.
62
+
We'll be using the GNU Debugger (`gdb`) to debug a couple of C++ programs.
63
63
`gdb`, like `g++`, is open source software.
64
-
There are GUI frontends available for `gdb`, but in this class, we'll be using the command line interface.
64
+
There are GUI frontends available for `gdb`, but in this chapter, we'll be using the command line interface.
65
65
66
66
### Takeaways
67
67
68
-
- Learn to debug C++ projects with `gdb`
69
-
- Step through the execution of a compiled C++ program
70
-
- Inspect the contents of program variables
68
+
- Learn general debugging practices
69
+
- Step through the execution of a compiled C++ program
70
+
- Inspect the contents of program variables
71
71
72
72
## Walkthrough
73
73
74
+
### Fatherly Debugging Advice
75
+
76
+
It's a sunny afternoon, so I take off work early and come by to pick you up from school.
77
+
You run up and hop in the front seat of the car.
78
+
"Hey kiddo, how was school? Do you want to get some ice cream?"
79
+
80
+
We drive over to the ice cream shoppe and I pull the ol' steering-with-my-knees trick
81
+
that always makes you scream. "Dad! Stop it, you'll hit someone!"
82
+
I laugh and mock-begrudingly put my hands back on the wheel.
83
+
84
+
We sit down in a booth to enjoy a couple of sundaes.
85
+
"How was your day? Are the other kids treating you well?" I ask.
86
+
87
+
"School was fine. I did great on my English paper! But..."
88
+
You furrow your brow.
89
+
90
+
"What's on your mind?"
91
+
92
+
"Well, some of my friends have been programming.
93
+
And sometimes their programs don't work, and they have to fix them.
94
+
And I guess I'm worried that when my program doesn't work I won't be able to fix it!"
95
+
96
+
"My child," I begin.
97
+
98
+
I put a hand on your shoulder the way only a father can.
99
+
100
+
"My dearest,"
101
+
102
+
I put another hand on your shoulder.
103
+
104
+
"It seems like only yesterday you were but a wee babe.
105
+
How you did cry and scream and do other things that babies do!
106
+
I lost more sleep over you than I did working 26 hour shifts at the smoke alarm testing factory."
107
+
108
+
I put another hand on your shoulder.
109
+
110
+
"But there was one thing that always calmed you down.
111
+
The instant I'd sit you next to a computer you'd smile and coo!
112
+
Many an evening I rocked you to sleep cradled between the screen and keyboard of a Thinkpad 701C.
113
+
That's when I knew you'd grow up to be a great programmer."
114
+
115
+
I put another hand on your shoulder. You are visibly embarrassed at this point.
116
+
117
+
"And now look at you! Practically all grown up!
118
+
Your mother and I are so proud of you.
119
+
Everyone has trouble with programs from time to time."
120
+
121
+
I put another hand on your shoulder.
122
+
123
+
"Here's what I do when I have to fix a program:"
124
+
125
+
#### 1. What happened? What should have happened?
126
+
127
+
You should have an idea of how your program ought to work in your mind while programming.
128
+
Maybe you've got a homework assignment writeup to go off of, or a design document that you wrote,
129
+
or just an idea in your head that you're implementing.
130
+
131
+
Regardless of where that idea comes from, take a second to identify the wrong behaviour you're seeing
132
+
and to figure out what your program should have done instead.
133
+
If you can, get a real piece of paper and actually draw out a picture of what your program is doing;
134
+
for example, if you're making a binary tree, draw the tree, or if you're communicating to a server,
135
+
draw/write out the protocol your server and client should be following.
136
+
137
+
#### 2. What the heck did you do to break it?!
138
+
139
+
Was your program working earlier?
140
+
If so, think through the changes you just made.
141
+
(You may find consulting `git diff` to be helpful!)
142
+
How might they have caused the bug?
143
+
144
+
(If your program didnt work right in the first place, you'll have to try some other debugging technique. Sorry.)
145
+
146
+
#### 3. How is the program getting the wrong result?
147
+
148
+
Start from where you saw the bug and work your way back through your program.
149
+
What execution path did it follow? What values do your variables have?
150
+
How do those values get set?
151
+
152
+
Make generous use of print (`cout`) statements! Print out the contents of your variables and
153
+
print out messages that tell you what code is executing.
154
+
Don't take anything for granted!
155
+
Use those print statements to check your assumptions about how your code works.
156
+
157
+
#### 4. Talk it out.
158
+
159
+
\afterpage{% Put bertha on her own page
160
+
\begin{figure}[p!]
161
+
\centering
162
+
\includegraphics[width=\textwidth]{08/bertha.png}
163
+
\caption{Bertha!}
164
+
\end{figure}
165
+
\clearpage
166
+
}
167
+
168
+
On the next page you will find Bertha.[^picture]
169
+
She's very curious about people and would love to hear about your program.
170
+
So, prop that page up next to your computer and explain exactly what is wrong with your program,
171
+
just like you would explain it to a friend.
172
+
Why do you think it's broken?
173
+
What fixes did you try?
174
+
175
+
(This may seem foolish, but this techinque once revealed to me that I had been debugging code
176
+
for an hour under the misapprehension that 9 was a prime number.
177
+
You'd be amazed at the things you don't realize until you think about how to explain something
178
+
to someone else.)
179
+
180
+
#### 5. When all else fails, try again later.
181
+
182
+
If you've got a bug that you just can't seem to figure out, take a break.
183
+
If there are other obvious bugs, fixing those may reveal the root cause of your problem bug.
184
+
Otherwise, take a walk, or even better, get a good night's sleep and come back to it in the morning.
185
+
186
+
These debugging tips work for any program (and plenty of not-computer-related problems to boot).
187
+
However, a debugger tool can make life easier for you, especially when you are tracing the execution
188
+
of your program and inspecting how it behaves.
189
+
74
190
### Compilin' for Debuggin'
75
191
76
-
When you compile a program, you lose a lot of information.
192
+
Compiled programs don't contain all the information that their source code does.
77
193
All of the C++ code that you write gets translated into machine-executable code.
78
194
As far as your CPU is concerned, there's really no need for function names, curly braces, or comments.
195
+
So, if you try to debug a program that's compiled in the usual manner, you'll have to wade through a lot of
196
+
hex numbers and assembly code.
79
197
80
-
As a human person, you will need those things.
81
-
82
-
If we plan to debug our code with `gdb`, we need to ask `g++` to to keep the details of our source code when we compile it.
198
+
As a human person, you'd rather be able to look at your actual source code in the debugger.
199
+
Fortunately, there is a way to ask `g++` to to keep the details of our source code when we compile it.
83
200
Whenever you compile your code, simply add the `-g` flag to your `g++ command`.
84
201
For example:
85
202
86
-
~~~shell
203
+
~~~
87
204
$ g++ -g main.cpp
88
205
~~~
89
206
90
207
If you forget the `-g`, `gdb` will have a lot less information to work with.
91
-
As a result, debugging will be much less useful.
208
+
As a result, debugging will be much less fun.
92
209
93
210
### Starting GNU Debugger
94
211
@@ -156,18 +273,18 @@ In order to debug your program, it has to be running.
156
273
The `run` command is likely one of the first commands you will run whenever you debug a program.
157
274
158
275
If you need to pass any command line arguments to the program, you'll pass them to the run command.
159
-
For example, if we wanted to debug `g++`[^dont]...
276
+
For example, if we wanted to debug `g++`...[^dont]
160
277
161
278
~~~
162
279
$ gdb g++
163
280
(gdb) run funcs.cpp main.cpp
164
281
~~~
165
282
166
-
...would be similar to running `g++ funcs.cpp main.cpp` outside of `gdb`.
283
+
...would be similar to running `g++ funcs.cpp main.cpp` outside of `gdb`.
167
284
168
285
#### Stopping at the right time
169
286
170
-
If you don't want your program to pause at a specific line, you can place a **breakpoint**.
287
+
If you want your program to pause at a specific line, you can place a **breakpoint**.
171
288
172
289
Assuming your program is not currently running, let's place a breakpoint at line 8 of `main.cpp`.
173
290
Then, we'll run our program.
@@ -194,13 +311,13 @@ For example:
194
311
195
312
~~~
196
313
(gdb) info breakpoints
197
-
1 breakpoint keep y 0x000000000040086c in main() at main.cpp:8
198
-
2 breakpoint keep y 0x000000000040088e in main() at main.cpp:10
199
-
3 breakpoint keep y 0x0000000000400894 in main() at main.cpp:12
314
+
1 breakpoint keep y 0x40086c in main() at main.cpp:8
315
+
2 breakpoint keep y 0x40088e in main() at main.cpp:10
316
+
3 breakpoint keep y 0x400894 in main() at main.cpp:12
200
317
(gdb) delete 2
201
318
(gdb) info breakpoints
202
-
1 breakpoint keep y 0x000000000040086c in main() at main.cpp:8
203
-
3 breakpoint keep y 0x0000000000400894 in main() at main.cpp:12
319
+
1 breakpoint keep y 0x40086c in main() at main.cpp:8
320
+
3 breakpoint keep y 0x400894 in main() at main.cpp:12
204
321
(gdb) delete
205
322
Delete all breakpoints? (y or n) y
206
323
(gdb) info breakpoints
@@ -216,12 +333,20 @@ You can use the `backtrace` command to ask `gdb` where we currently are.
216
333
#0 main () at main.cpp:8
217
334
~~~
218
335
219
-
In the output, `gdb` will show you the current backtrace.
220
-
Depending how many functions you've called, you'll see deeper and deeper traces.
336
+
The backtrace shows you the function stack: starting from `main()`,
337
+
which functions were called to get to the line that's currently executing?
338
+
Think of it like a family history: this line of code lives in this function,
339
+
which was called by this other function, which was called by *another* function,
340
+
and so on and so forth all the way back to Adam, err, `main()`.
221
341
In this case, we've only called `main()`, so that's the only line we see.
222
-
You can also see the file name and line number.
342
+
You can also see the file name and line number where the function is defined,
343
+
along with the values of any arguments passed to it.
344
+
345
+
`backtrace` is usually the first tool you should reach for when debugging a segfault.
346
+
It'll tell you right where your program is, and it might even show you the null pointer
347
+
(if you're passing it as an argument to the function).
223
348
224
-
You can also use `list` to ask `gdb` to show you some source code to give you context.
349
+
You can use `list` to ask `gdb` to show you some source code to give you context.
225
350
Sometimes a line number isn't enough if you're too lazy to tab over to your text editor.
226
351
227
352
~~~
@@ -307,8 +432,37 @@ $2 = 7
307
432
That makes a lot more sense!
308
433
309
434
You can use `print` to print out any variable that's in scope.
310
-
You can also use `info locals` to check on the value of local variables.
311
-
Try running it and make a note of the output.
435
+
It even knows how to print out struct and class instances!
436
+
437
+
`print` will also happily print out the results of C++ expressions.
438
+
You can dereference pointers, do arithmetic, and even call functions!
439
+
440
+
For a summary of all the variables in the current function, use `info locals`.
441
+
`info` can show a bunch of other interesting data about your program and about `gdb`.
442
+
443
+
#### Setting the contents of variables
444
+
445
+
Sometimes you'll want to test out a theory --- maybe you think you've found your bug, and you want to
446
+
make a quick change to see if you know how to fix it.
447
+
You can't change the code while `gdb` is running it, but you can poke stuff in memory to your heart's content.
448
+
449
+
You can change the values of variables on the fly with the `set` command:
450
+
451
+
~~~
452
+
(gdb) print x
453
+
$1 = 7
454
+
(gdb) set x = 30
455
+
(gdb) print x
456
+
$2 = 30
457
+
(gdb) step
458
+
11 if (x >= 10)
459
+
~~~
460
+
461
+
Here, instead of continuing execution on line 9, the code jumps to line 11 since we changed the value of `x`!
462
+
463
+
There's a lot more that `gdb` can do --- disassembling functions, poking around in memory, debugging code running on other machines ---
464
+
but the stuff in this chapter will cover all of your usual debugging needs.
0 commit comments