forked from aaronbloomfield/pdr
-
Notifications
You must be signed in to change notification settings - Fork 228
/
index.html
540 lines (537 loc) · 29.3 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>PDR: GDB Tutorial</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<link rel="stylesheet" href="../../markdown.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="pdr-gdb-tutorial">PDR: GDB Tutorial</h1>
<p><a href="../index.html">Go up to the Tutorials table of contents
page</a></p>
<p>This tutorial is meant to get you used to using the GNU debugger,
gdb. As you read through the first part of the tutorial, you are not
expected to remember everything – there is a reference list at the end
of this tutorial, and is also contained on the <a
href="../../docs/gdb_summary.html">GDB command summary</a> page. This
tutorial will guide you through the process of using those commands.</p>
<p>Some terminology:</p>
<ul>
<li><code>gdb</code> is a command-line debugger (we may see graphical
debuggers later in the semester.)</li>
<li>“GNU” is the compiler framework that includes many things, including
a compiler (<code>g++</code>) as well as the debugger
<code>gdb</code></li>
<li>“LLVM” is the compiler framework that includes many things,
including a compiler (<code>clang++</code>) as well as the debugger
<code>lldb</code></li>
<li><code>lldb</code> is the debugger that is often used elsewhere – it
is analogous to <code>gdb</code> in how it works</li>
</ul>
<p>Note that the gdb debugger is designed to work with a different
compiler (g++). However, the lldb debugger, which is designed to work
with clang++, does not work on an Ubuntu VirtualBox installation (see <a
href="http://llvm.org/bugs/show_bug.cgi?id=20446">here</a> for the bug
tracker about this issue). Thus, we are going to use gdb instead of
lldb.</p>
<hr />
<h2 id="part-i-gdb-tutorial">Part I: GDB Tutorial</h2>
<h3 id="what-is-a-debugger">What is a Debugger?</h3>
<p>A debugger is a utility program that allows you to run a program
under development while controlling its execution and examining the
internal values of variables. We think of a program running “inside” a
debugger. The debugger allows us to control the execution of the program
by pausing its execution and then resuming it. While paused, we can find
out where we are in the program, what values variables have, reset the
values of variables, etc. If a program crashes, the debugger can tell
you exactly <em>where</em> the program crashed (something that Java does
naturally, but C++ does not). The principles and commands described in
this document are specific to the gdb debuggers for clang++ under UNIX,
but every debugger has similar commands.</p>
<p>All computer scientists should learn the basics of debugging and how
to use a debugger. It will save you literally hours of time when finding
and fixing problems in your programs. The few minutes of investment you
put into learning how to use a debugger will pay off tremendously in a
matter of weeks. Work smart!</p>
<h3 id="sample-program">Sample Program</h3>
<p>Consider the following buggy program into <a
href="prog1.cpp.html">prog1.cpp</a> (<a href="prog1.cpp">src</a>):</p>
<pre><code>#include <iostream>
using namespace std;
void my_subroutine() {
cout << "Hello world" << endl;
}
int main() {
int x = 4;
int *p = NULL;
my_subroutine();
*p = 3;
cout << x << ", " << *p << endl;
return 0;
}</code></pre>
<p>This program will throw a segmentation fault every time (as we are
trying to dereference a <code>NULL</code> pointer), but that’s fine for
what we want to do here.</p>
<h3 id="compiling-for-debugging">Compiling for Debugging</h3>
<p>Programs normally have to be compiled with a special option to allow
debugging to take place. On UNIX, the option for clang++ is the
<code>-g</code> option. For example:</p>
<pre><code>clang++ -Wall -g -o prog1 prog1.cpp </code></pre>
<p>We also include the <code>-Wall</code> option, which lists warnings
(the ‘all’ is to list all warnings). Note that this option leads to
executable files that are larger and slower, so you may not want to use
it for final distributions or time-critical programs. But you can always
remove the debugging information from an executable without recompiling
it with the <code>strip</code> command. For more information on that,
see the man page for <code>strip</code> (i.e., run <code>man
strip</code> from the command line).</p>
<p>The <code>-g</code> option causes the compiler to include information
about the source file (the .cpp file) that is needed for debugging as
part of the executable file. This causes the executable to be larger in
size, and slightly slower, but allows for debugging. So when you run the
debugger, you specify the executable file (not the source file) as the
input to the debugger.</p>
<h3 id="how-to-start-using-gdb-on-our-unix-systems">How to Start Using
gdb on our UNIX Systems</h3>
<p>The LLVM C++ compiler, clang, has an accompanying debugger: lldb.
However, that has issues with Ubuntu running on VirtualBox, so we are
going to use the <code>gdb</code> debugger. To run the command-line
version, compile your program as described above, and then type:</p>
<pre><code>gdb prog1</code></pre>
<p>This was assuming your executable (created with clang’s
<code>-o</code> option) was “prog1”. If you didn’t use the -o option,
then you’ll type:</p>
<pre><code>gdb a.out</code></pre>
<p>The following sections describe the important types of things you can
do with gdb, organized by “category” of activity. These activities and
operations will have been implemented in other debuggers you may have
used, such as the debuggers that come with various IDEs.</p>
<h3 id="executing-your-program">Executing your Program</h3>
<p>Once in gdb, use the <code>run</code> command to start your program
running. It will run until it completes, until it crashes, or until it
reaches a breakpoint that you set (more on this later) – and it will
pause for input, of course. Once it finishes, you’re still in gdb, so
you can run it again from the beginning.</p>
<p>If your program requires command-line arguments, you can give them
after the run command. If you would normally run the program on the
command line by entering:</p>
<pre><code>prog1 100 test1.dat</code></pre>
<p>In the debugger, you would enter:</p>
<pre><code>run 100 test1.dat</code></pre>
<p>Note, however, that the prog1 that we are editing here does not need
any command line parameters.</p>
<h3 id="where-am-i-where-did-it-crash">Where Am I? Where Did It
Crash?</h3>
<p>Under UNIX, one of the most frustrating things about running C or C++
programs is that they normally give little useful information when they
crash – usually they just say, ‘segmentation fault’. Part of the reason
is that by default the executable file doesn’t include information about
the source code that is needed to print an error message (like the line
number).</p>
<p>But when you run a program inside a debugger, you can easily see what
the current line is when a program crashes. Type <code>list</code> to
see the current and surrounding lines.</p>
<p>More usefully, you can see a list of the function calls that led you
to this point in your program. Your program may have died deep inside a
function that is called many times in your program, and you need to know
which sequence of nested functions calls led to the failure. In the
command-line mode, type <code>backtrace</code> or <code>bt</code> to
show this list. IMPORTANT: this command is one of the most important and
useful debugging commands you’ll see in this lesson!</p>
<p>While we’re talking about reaching a point in a sequence of nested
function calls, sometimes in gdb you will need to understand the concept
of frames. When a program stops, you can examine local variables, view
lines of code, etc. that are local to that function. If you need to move
up to the function that called this one, you need to move up to the
higher frame using the <code>up</code> command to debug there. The
<code>down</code> command moves you back down a frame towards where you
started. The up and down commands let you move up and down the calling
stack (of nested function calls) so you can issue debug commands about
the function that’s “active” at each level.</p>
<h3 id="making-your-program-pause-breakpoints">Making your Program
Pause: Breakpoints</h3>
<p>One of the most fundamental things you want to do while debugging is
make the program pause at a particular line or at the start of a
function. These locations in a program where execution pauses are called
“breakpoints.” IMPORTANT: You must choose a line of code that actually
executes something: not a comment, for example.</p>
<p>In gdb you can set breakpoints by typing either <code>break</code> or
<code>b</code> followed by information on where you want the program to
pause. After the <code>b</code> command, you can put either:</p>
<ul>
<li>a function name (e.g., <code>b my_subroutine</code>)</li>
<li>a line number (e.g., <code>b 12</code>)</li>
<li>either of the above preceded by a file name (e.g., <code>b
prog1.cpp:12</code> or <code>b prog1.cpp:my_subroutine</code>)</li>
</ul>
<p>Here, the <code>my_subroutine()</code> function doesn’t start on line
12 (it starts on line 4) – the breakpoint on line 12 is for the
<code>NULL</code> pointer dereference in the <code>main()</code>
function. We could have also set a breakpoint at the beginning on the
my_subroutine() function by calling <code>b 4</code>.</p>
<p>At any time you can see information about all the breakpoints that
have been defined by entering <code>info breakpoints</code> (or
<code>info break</code>). You can remove a breakpoint using the
<code>delete</code> command (or just <code>d</code>). You can delete all
breakpoints (<code>d</code>) or a specific one (<code>d 1</code> or
<code>d my_subroutine</code>).</p>
<p>Breakpoints stick around until you delete them. This is handy if you
put a breakpoint inside a function that is called more than once or if
you put one inside a loop. You can set a temporary breakpoint with the
<code>tbreak</code> command; the program pauses the first time, but
after it pauses there, that breakpoint is cleared.</p>
<p>An important thing to keep in mind with breakpoints is that if you
set a breakpoint for line 12, then the program will pause BEFORE
executing that line.</p>
<h3 id="controlling-execution-after-a-breakpoint">Controlling Execution
After a Breakpoint</h3>
<p>After you make your program pause, you may want to execute it
line-by-line to see what it does next. There are two commands that make
a program execute the next line and then pause again: <code>next</code>
and <code>step</code>.</p>
<p>The difference between these two is how they behave when the program
reaches a function call. The <code>step</code> command steps into that
function; in other words, you see the debugging session move into the
called function. The <code>next</code> command steps over that function
call, and you see the current line as the one after the function call.
Both are useful, depending on what level of detail you need.</p>
<p>Sometimes after you’ve hit a break point and are doing line-by-line
execution, you want to resume normal execution until the next breakpoint
is reached (or the program completes). The command to do this is
<code>continue</code>. A useful variant on this is the
<code>finish</code> command which finishes executing the current
function and then pauses.</p>
<p>You can use the abbreviations <code>s</code>, <code>n</code> and
<code>c</code> for the common commands described in this section.</p>
<h3 id="displaying-variables-and-expressions">Displaying Variables and
Expressions</h3>
<p>Another thing you often want to do when the program pauses is to see
what value a variable or an expression has. To do this, just type
<code>print</code> or <code>p</code> followed by the variable name or
expression. If the variable or expression is a pointer or an address,
you can print the value that this address references using the
<code>print *</code> command (i.e. <code>print *foo</code>). In
addition, you can enter <code>info locals</code> to see all the
arguments and local variables (and their values) displayed.</p>
<p>It is often handy to have the debugger automatically display one or
more variable values at all times so you could watch how they change.
You do this with the <code>display <var></code> command, and gdb
will display that variable’s value each time the program execution hits
a breakpoint. You can use ‘display’ more than once to show multiple
variables.</p>
<p>To see info on all variables chosen for display, just enter
<code>display</code>. To remove a variable from the automatic display
list, use the <code>undisplay</code> command followed by the display
variable’s numeric-id (entering <code>display</code> shows the
variables’ numeric ids).</p>
<h3 id="changing-a-variables-value">Changing a Variable’s Value</h3>
<p>If you see that a variable has the wrong value, and you’d like to
change that value in mid-stream before continuing execution, you can do
this easily. Enter <code>set</code> followed by the type, then the
variable, an equals symbol (<code>=</code>), and the value or
expression. It’s just like a C++ assignment statement but without the
semi-colon at the end. For example:</p>
<pre><code>set variable x = 5</code></pre>
<p>The expression can be any C++ expression, including a function call.
So a statement like this is legal:</p>
<pre><code>set variable y = countNegValues(list, num)</code></pre>
<p>Assuming you have a <code>countNegValues()</code> method defined, of
course. This would execute your function and then set the variable y to
be whatever your function returns.</p>
<p>Sometimes you want to actually execute a function “by hand” while the
program is stopped, even if this function isn’t what would normally be
called at this point in the code. You can do this using the
<code>set</code> command as shown above, or by making the function call
the argument to the print command. For example, you could type:</p>
<pre><code>print initQueue(&myQueue)</code></pre>
<p>And the function would be called right now while the program is
paused. This works even if the function returns void.</p>
<h3 id="trying-these-commands-out">Trying these commands out</h3>
<p>Compile and run the prog1.cpp file shown above; this should segfault.
The problem is on line 12, when it tries to dereference the NULL
pointer.</p>
<p>Run it in GDB with the program (<code>gdb prog</code>), and try the
following:</p>
<ul>
<li>type <code>run</code>, and let it run to completion (really until it
crashes)</li>
<li>try the <code>bt</code> and <code>list</code> commands</li>
<li>set up a break point at line 12, which is the line that is causing
the crash</li>
<li>type <code>run</code>, and confirm that you want to restart the
program</li>
<li>at the breakpoint, try printing out the value in p (<code>p
p</code>); note that it is <code>NULL</code></li>
<li>set the <code>p</code> pointer, which is currently
<code>NULL</code>, to point to a valid value (the <code>int</code>
variable <code>x</code>): <code>set variable p = &x</code></li>
<li>enter <code>c</code> to let it continue running, and it should
finish without crashing this time</li>
</ul>
<h3 id="frames">Frames</h3>
<p>When a program crashes, you can see the list of subroutine calls that
led to that point via the ‘bt’ command. This prints a <em>stack
trace</em>, similar to what Java prints when an exception is thrown (but
not caught). Each level in that stack trace is called a <em>frame</em>.
Sometimes you may want to look at the variables and what-not a few
frames up. To do so, you enter the <code>frame</code> command. Consider
the following program:</p>
<pre><code>#include <iostream>
using namespace std;
void recurse(int x) {
int *y = NULL;
if ( x == 0 )
cout << *y << endl;
recurse(x-1);
}
int main() {
recurse(5);
return 0;
}</code></pre>
<p>This program will crash on the 5th recursive call to
<code>recurse()</code>. If this program is compiled (remember to compile
it with <code>-g</code>) and run through the debugger, it will crash,
and the resulting stack trace looks like the following:</p>
<pre><code>(gdb) bt
#0 0x000000000040084a in recurse (x=0) at frame.cpp:6
#1 0x0000000000400872 in recurse (x=1) at frame.cpp:7
#2 0x0000000000400872 in recurse (x=2) at frame.cpp:7
#3 0x0000000000400872 in recurse (x=3) at frame.cpp:7
#4 0x0000000000400872 in recurse (x=4) at frame.cpp:7
#5 0x0000000000400872 in recurse (x=5) at frame.cpp:7
#6 0x0000000000400882 in main () at frame.cpp:10
(gdb) </code></pre>
<p>The frames are listed on the left-hand side, and you can enter
<code>frame 4</code> (or whatever value) to move to that frame. You can
then examine the contents of the variables in that frame before moving
on.</p>
<h3 id="a-few-final-commands">A few final commands</h3>
<p>If you find the problem while using the debugger, you may want to
exit gdb (by entering <code>quit</code>), recompile your source code,
and restart gdb. Be sure to use the <code>-g</code> option when
recompiling!</p>
<h3 id="final-remarks">Final Remarks</h3>
<p>The best way to learn these commands is to try them out. Even if you
don’t use a debugger often, you should make sure you know the basics of
breakpoints, single-line execution, and printing a variable’s value.
These commands, along with the <code>backtrace</code> command, will be
enough for you to solve most of your problems.</p>
<p>Again, a programmer must know how to use a debugger just like an
accountant must know how to use a spreadsheet program or a calculator.
Your professors and your boss will expect it of you. Remember this
before you go see your instructor about a run-time bug next time! The
time you spend now to learn how to use a debugger will save you hours in
the future.</p>
<hr />
<h2 id="part-ii-gdb-lab-exercise">Part II: GDB Lab Exercise</h2>
<h3 id="the-source-code">The Source Code</h3>
<p>We will be using the <a href="debug.cpp.html">debug.cpp</a> (<a
href="debug.cpp">src</a>) source code. There are a few errors in the
code, but don’t fix them! We’ll use the debugger to find them.</p>
<h3 id="running-the-debugger">Running the Debugger</h3>
<p>After you enter the code (remember: if you spot the errors do not
correct them – we will use the debugger to find them!), compile the
code. If you plan on using the debugger, you have to specifically tell
clang++ to include debugging information. To do that, enter the
<code>-g</code> flag. For example, enter:</p>
<pre><code>clang++ -Wall -g -o lab2 debug.cpp</code></pre>
<p>The <code>-g</code> flag will include debugging information. The
<code>-o lab2</code> flag will cause the output executable to be
<code>lab2</code>. The <code>-Wall</code> flag is a new one – it will
include all warnings about your code (errors are still reported without
the flag; this includes warnings as well).</p>
<p>There are no compiler or linker errors (or warnings!), so if you get
any you will need to find and fix them. We should now be ready to
go.</p>
<p>First just run the program, and enter the numbers 2, 4, 6, 8, and 10
– we’ll be using those five numbers throughout the debugging of the
program. The first thing that you should see is that these are not the
numbers that the program displays back to you! What happened? What’s
wrong? Let’s use the debugger to find out.</p>
<p>The first feature we will use is the ability to set a breakpoint.</p>
<h3 id="setting-up-breakpoints">Setting up Breakpoints</h3>
<p>Remember that a breakpoint is any point in the executable code where
the execution stops, allowing the programmer to see what is going on
inside the program as it runs. Breakpoints allow you to run through
portions of the code where there are no problems, so that you can spend
your time focusing on the areas that need to be fixed.</p>
<p>To set up a breakpoint, you enter the ‘break’ command, and where you
want the breakpoint to be. There are 3 ways to specify breakpoints, by
entering:</p>
<ul>
<li>a function name (e.g., <code>b GetAverage</code>)</li>
<li>a line number (e.g., <code>b 23</code>)</li>
<li>either of the above preceded by a file name (e.g., <code>b
debug.cpp:23</code> or <code>b debug.cpp:GetAverage</code>)</li>
</ul>
<p>If we knew where the problems were, we could skip over some lines,
but since we don’t, put a breakpoint on the first line of the code, the
cout statement. You probably want to set the breakpoint based on the
line number in the code – you can use the Emacs command <code>M-x
linum-mode</code> to have Emacs display line numbers. Enter <code>break
x</code>, where x is the line of the first cout statement in the main()
method. Now we need to run the program – to do this, enter
<code>run</code>. Gdb should start running, then should pause and
display approximately the following:</p>
<pre><code>(gdb) break 23
Breakpoint 1 at 0x400a0f: file debug.cpp, line 23.
(gdb) run
Starting program: /home/aaron/Dropbox/git/pdr/tutorials/02-gdb/a.out
Breakpoint 1, main () at debug.cpp:23
23 cout << "Enter five numbers: " << endl;
(gdb) list
18
19 int nValues[MAX];
20 int nCount;
21
22 // Display a prompt:
23 cout << "Enter five numbers: " << endl;
24
25 // First we read in the numbers.
26 for ( nCount = 0; nCount < MAX; nCount++ ) {
27 cout << "Enter the next number : ";
(gdb)</code></pre>
<p>Gdb is stating that it hit a breakpoint, on line 23 of debug.cpp, and
displays the line of code. There are a number of commands we can enter
at this point (try them all):</p>
<ul>
<li><code>bt</code>: shows a list of the function calls that got us to
this point (we are only in the main() method at this point, so it’s not
all that interesting)</li>
<li><code>list</code>: shows a listing of the source code where the
breakpoint occurred</li>
<li><code>info locals</code> shows the current variables, and their
values. Note that the variables have not been initialized, so they have
strange values!</li>
<li><code>p nCount</code> will print the current value in nCount</li>
<li><code>p nValues</code> shows all the values in the array
nValues</li>
</ul>
<h3 id="examining-data">Examining Data</h3>
<p>One of the most powerful features of the debugger is the ability to
look at the state of the variables as the program executes. This way the
programmer can see if the variables are changing the way that they are
intended to change, and to see if the program is doing the things that
were intended.</p>
<p>The <code>info locals</code> command will show all the local
variables of the current scope of execution. Which variables are
displayed will change as the program executes, always showing the most
recently defined variables, values returned from functions, and changed
or referenced variables. When our test program hits the breakpoint, two
variables are shown: nCount and nValues. nCount will be some random
integer which reflects the contents of that memory location at the
beginning of the program. The nValues variable looks different – it’s an
array, so the entire contents of the array are shown.</p>
<h3 id="stepping-through-the-code">Stepping through the Code</h3>
<p>Gdb allows you to step through the code in two different ways. You
can execute one line at a time, stepping into each function call, or you
can run the functions without tracing their execution. We will look at
examples of both.</p>
<p>First, let’s see what happens when we start the program. You should
now be at the breakpoint from above – if not, restart the program
(<code>run</code>) – it will break at the breakpoint you entered before.
Entering <code>info locals</code> shows that the nCount variable is
filled with a random number. Let’s step into the loop and see what
happens.</p>
<p>First, we’ll start by stepping OVER commands.</p>
<h3 id="single-stepping-through-your-code">Single Stepping through your
code</h3>
<p>Enter <code>n</code> (or <code>next</code>) – this steps OVER the
next command. This stepped over the <code>cout</code> command – if we
had entered <code>s</code>, it would have started showing the execution
of the cout function call, which is not what we want. Note after we
entered the <code>n</code>, it showed the output (“Enter five numbers:”)
to the screen. We were stopped BEFORE the line executed, so by single
stepping, we caused the computer to execute that one line. Nothing else
has changed (<code>info locals</code>, <code>bt</code>, etc. are the
same), so let’s press <code>n</code> again.</p>
<p>Now the cout statement inside the for loop is the current line. Also
notice that now the nCount variable (via <code>info locals</code> or
<code>print nCount</code>) has a value - it is zero, because that’s
where our for loop begins. Press <code>n</code> again. The prompt for
the next number is displayed, since the cout statement has executed.
Step through another line of code.</p>
<p>The code is now stopped on the <code>cin</code> statement. You will
need to enter a value and press enter.</p>
<p>You should see these changes:</p>
<ul>
<li>The number you typed shows after the prompt.</li>
<li><code>info locals</code> shows that the 2 was entered into the array
at index 1 (not 0!)</li>
</ul>
<p>Pressing <code>n</code> again will take us to the beginning of the
loop; pressing it again will increment the value of nCount in the watch
windows. Let’s single step through another pass through the loop. Step
over button twice more, entering successive values when prompted (2, 4,
6, 8, 10). See what happens to the variables.</p>
<p>This shows you one of the errors - the data is all going into
nValues[1]. Go to the source window, and correct the line. Exit gdb
(<code>quit</code>), recompile the program, and start up gdb again
(<code>gdb lab2</code>). Set your breakpoint, run the code, and make
sure that it is getting the input correctly. Try entering <code>display
nValues</code> after the first breakpoint – it will always display the
contents of the nValues array each time the program pauses.</p>
<p>When you are satisfied that the input is working, you can
<code>continue</code> (or <code>c</code>), and the program will run
until the next breakpoint, or the end of the program.</p>
<p>There appears to be a couple more errors in the code. Let’s address
the problem with the average value. To do this we’ll need to use the
step into ability of the debugger.</p>
<p>Place a breakpoint on the line that the GetAverage() function is
called (the cout line in the main() method, not the GetAverage() method
itself). Remove the breakpoint from the beginning of the source code:
<code>delete <line></code>, where <line> is the line of code where
the breakpoint is at, or <code>delete 1</code>, where 1 is the
breakpoint number. You can see the list of breakpoints by entering
<code>info break</code>. Once you have only one breakpoint set up at
line that GetAverage() is called, run your code (<code>run</code>). It
will run normally (we’ll enter the same values: 2, 4, 6, 8, 10) until it
hits the breakpoint.</p>
<p>Press the Step Into button (<code>s</code>). Execution of the program
now passes to the first line of the function GetAverage(). Entering
<code>bt</code> will show the series of function calls that got us to
this point. We can now use the step over command (<code>n</code>) to
step through the function and identify the errors.</p>
<p>A word of caution: using the step into command at the wrong time may
cause the debugger to load and display either assembly language or
unfamiliar code. Don’t worry; all you’ve done is stepped into the code
for a standard function or operator such as the insertion operator. To
exit this code, enter <code>c</code> for continue (which will continue
execution until the next breakpoint), or <code>finish</code>, which will
execute until the current function ends.</p>
<p>Does the printing of the maximum value work? If so, great! If not,
you get to figure that one out on your own…</p>
<h3 id="explore-on-your-own">Explore on your own</h3>
<p>There are still a few errors; try tracing through the function and
see what you can fix! Remember that there are a few different types of
breakpoints. Rather than entering the line number, you can enter a
breakpoint by specifying the function call – for example, you can enter
‘break GetAverage’ to debug the GetAverage function, rather than trying
to figure out which line the function starts on.</p>
<h3 id="finishing-up">Finishing up</h3>
<p>When you are finished debugging the code with gdb – and it works
correctly – you should submit the debug.cpp file to inlab2. Remember to
put your identifying information at the top.</p>
<hr />
<h2 id="part-iii-summary-of-gdb-commands">Part III: Summary of gdb
commands</h2>
<p>These commands are listed on the <a
href="../../docs/gdb_summary.html">GDB command summary</a> page.</p>
<p>You can see a difference between the commands of lldb and gdb on the
<a href="../../docs/gdb_vs_lldb.html">GDB vs LLDB commands</a> page.</p>
</body>
</html>