Debugging((Part(1) - cs.princeton.edu
Transcript of Debugging((Part(1) - cs.princeton.edu
1
Debugging (Part 1)Aarti Gupta
The material for this lecture is drawn, in part, fromThe Practice of Programming (Kernighan & Pike) Chapter 5
For Your AmusementāWhen debugging, novices insert corrective code;; experts remove defective code.ā
-Ā-Ā Richard Pattis
āIf debugging is the act of removing errors from code, what's programming?ā
-Ā-Ā Tom Gilb
āDebugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.ā
-Ā-Ā Brian Kernighan2
For Your Amusement
3
The first computer bug(found in the Harvard Mark II computer)
āProgramming in the Largeā StepsDesign & Implementā¢ Program & programming style (done)ā¢ Common data structures and algorithmsā¢ Modularityā¢ Building techniques & tools (done)
Testā¢ Testing techniques (done)
Debugā¢ Debugging techniques & tools <-- we are here
Maintainā¢ Performance improvement techniques & tools
4
5
Goals of this Lecture
Help you learn about:ā¢ Strategies and tools for debugging your code
Why?ā¢ Debugging large programs can be difficultā¢ A power programmer knows a wide variety of debugging strategiesā¢ A power programmer knows about tools that facilitate debuggingā¢ Debuggersā¢ Version control systems
6
Testing vs. Debugging
Testingā¢ What should I do to try to break my program?
Debuggingā¢ What should I do to try to fix my program?
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for familiar bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
7
8
Understand Error MessagesDebugging at build-Ātime is easier than debugging at run-Ātime, if and only if youā¦
Understand the error messages!
#include <stdioo.h>/* Print "hello, world" to stdout and
return 0. int main(void) printf("hello, world\n");
return 0;
What are the errors? (No fair looking at the next slide!)
9
Understand Error Messages
#include <stdioo.h>/* Print "hello, world" to stdout and
return 0. int main(void) printf("hello, world\n");
return 0;
Which tool (preprocessor, compiler, or linker) reports the error(s)?
$ gcc217 hello.c -o hellohello.c:1:20: error: stdioo.h: No such file or directoryhello.c:2:1: error: unterminated commenthello.c:7: warning: ISO C forbids an empty translation unit
10
Understand Error Messages
#include <stdio.h>/* Print "hello, world" to stdout and
return 0. */ int main(void) printf("hello, world\n")
return 0;
What are the errors? (No fair looking at the next slide!)
11
Understand Error Messages
#include <stdio.h>/* Print "hello, world" to stdout and
return 0. */ int main(void) printf("hello, world\n")
return 0;
Which tool (preprocessor, compiler, or linker) reports the error?
$ gcc217 hello.c -o hellohello.c: In function 'main':hello.c:6: error: expected ';' before 'return'
12
Understand Error Messages
#include <stdio.h>/* Print "hello, world" to stdout and
return 0. */ int main(void) prinf("hello, world\n");
return 0;
What are the errors? (No fair looking at the next slide!)
13
Understand Error Messages
#include <stdio.h>/* Print "hello, world" to stdout and
return 0. */ int main(void) prinf("hello, world\n")
return 0;
$ gcc217 hello.c -o hellohello.c: In function 'main':hello.c:5: warning: implicit declaration of function 'prinf'/tmp/ccLSPMTR.o: In function `main':hello.c:(.text+0x1a): undefined reference to `prinf'collect2: ld returned 1 exit status
Which tool (preprocessor, compiler, or linker) reports the error?
14
Understand Error Messages
#include <stdio.h>#include <stdlib.h>enum StateType STATE_REGULAR,
STATE_INWORDint main(void) printf("just hanging around\n");
return EXIT_SUCCESS;
What are the errors? (No fair looking at the next slide!)
15
Understand Error Messages
#include <stdio.h>#include <stdlib.h>enum StateType STATE_REGULAR,
STATE_INWORDint main(void) printf("just hanging around\n");
return EXIT_SUCCESS;
$ gcc217 hello.c -o hellohello.c:7: error: two or more data types in declaration specifiershello.c:7: warning: return type of 'main' is not 'int'
What does this error message even mean?
16
Understand Error MessagesCaveats concerning error messagesā¢ Line # in error message may be approximateā¢ Error message may seem nonsensicalā¢ Compiler may not report the real error
Tips for eliminating error messagesā¢ Clarity facilitates debuggingā¢ Make sure code is indented properly
ā¢ Look for missing semicolonsā¢ At ends of structure type definitionsā¢ At ends of function declarations
ā¢ Work incrementallyā¢ Start at first error messageā¢ Fix, rebuild, repeat
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for familiar bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
17
18
Think Before WritingInappropriate changes could make matters worse, soā¦
Think before changing your codeā¢ Explain the code to:ā¢ Yourselfā¢ Someone elseā¢ A Teddy bear?
ā¢ Do experimentsā¢ But make sure theyāre disciplined
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for common bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
19
20
Look for Common BugsSome of our favorites:
int i;ā¦scanf("%d", i);
char c;ā¦c = getchar();
switch (i) case 0:
ā¦break;
case 1:ā¦
case 2:ā¦
if (i = 5)ā¦
if (5 < i < 10)ā¦
if (i & j)ā¦
while (c = getchar() != EOF)ā¦
What are the errors?
21
Look for Common BugsSome of our favorites:
for (i = 0; i < 10; i++) for (j = 0; j < 10; i++)
...
What are the errors?
for (i = 0; i < 10; i++) for (j = 10; j >= 0; j++)
...
22
Look for Common BugsSome of our favorites:
int i;ā¦i = 5;if (something) int i;
ā¦i = 6;ā¦
ā¦printf("%d\n", i);ā¦
What value is written if this statement is present? Absent?
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for common bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
23
24
Divide and ConquerDivide and conquer: To debug a programā¦
ā¢ Incrementally find smallest input file that illustrates the bug
ā¢ Approach 1: Remove inputā¢ Start with fileā¢ Incrementally remove linesuntil bug disappears
ā¢ Examine most-Ārecently-Āremoved lines
ā¢ Approach 2: Add inputā¢ Start with small subset of fileā¢ Incrementally add linesuntil bug appears
ā¢ Examine most-Ārecently-Āadded lines
25
Divide and ConquerDivide and conquer: To debug a moduleā¦
ā¢ Incrementally find smallest client code subset that illustrates the bug
ā¢ Approach 1: Remove codeā¢ Start with test clientā¢ Incrementally remove lines of code until bug disappearsā¢ Examine most-Ārecently-Āremoved lines
ā¢ Approach 2: Add codeā¢ Start with minimal clientā¢ Incrementally add lines of test client until bug appearsā¢ Examine most-Ārecently-Āadded lines
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for common bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
26
27
Add More Internal Tests
(5) Add more internal tests
ā¢ Internal tests help find bugs (see āTestingā lecture)
ā¢ Internal test also can help eliminate bugsā¢ Validating parameters & checking invariantscan eliminate some functions from the bug hunt
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for common bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
28
29
Display OutputWrite values of important variables at critical spots
ā¢ Poor:
ā¢ Maybe better:
ā¢ Better:
printf("%d", keyvariable);
stdout is buffered;; program may crash before output appears
printf("%d", keyvariable);fflush(stdout);
printf("%d\n", keyvariable);
Call fflush() to flush stdout buffer explicitly
Printing '\n' flushes the stdout buffer, but not if stdout is redirected to a file
30
Display Output
ā¢ Maybe even better:
ā¢ Maybe better still:
fprintf(stderr, "%d", keyvariable);
FILE *fp = fopen("logfile", "w");ā¦fprintf(fp, "%d", keyvariable);fflush(fp);
Write debugging output to stderr;; debugging output can be separated from normal output via redirection
Write to a log file
Bonus: stderr is unbuffered
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for common bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
31
32
Use a Debugger
Use a debugger
ā¢ Alternative to displaying output
33
The GDB Debugger
GNU Debuggerā¢ Part of the GNU development environmentā¢ Integrated with Emacs editorā¢ Allows user to:ā¢ Run programā¢ Set breakpointsā¢ Step through code one line at a timeā¢ Examine values of variables during runā¢ Etc.
For details see precept tutorial, precept reference sheet, Appendix 1
Agenda(1) Understand error messages
(2) Think before writing
(3) Look for common bugs
(4) Divide and conquer
(5) Add more internal tests
(6) Display output
(7) Use a debugger
(8) Focus on recent changes
34
35
Focus on Recent ChangesFocus on recent changes
ā¢ Corollary: Debug now, not later
Easier:
(1) Compose a little(2) Test a little(3) Debug a little(4) Compose a little(5) Test a little(6) Debug a littleā¦
Difficult:
(1) Compose entire program(2) Test entire program(3) Debug entire program
36
Focus on Recent ChangesFocus on recent change (cont.)
ā¢ Corollary: Maintain old versions
Difficult:
(1) Change code(2) Note new bug(3) Try to remember whatchanged since last version
Easier:
(1) Backup current version(2) Change code(3) Note new bug(4) Compare code with last version todetermine what changed
37
Maintaining Old VersionsTo maintain old versionsā¦
Approach 1: Manually copy project directory
ā¦$ mkdir myproject$ cd myproject
Create project files here.
$ cd ..$ cp ār myproject myprojectDateTime$ cd myproject
Continue creating project files here.ā¦
38
Maintaining Old Versions
Approach 2: Use the Revision Control System (RCS)ā¢ A simple version control systemā¢ Provided with many Linux distributionsā¢ Available on CourseLab
ā¢ Allows programmer to:ā¢ Check-Āin source code files from working copy to repositoryā¢ RCS saves old versions
ā¢ Check-Āout source code files from repository to working copyā¢ Can retrieve old versions
ā¢ Appropriate for one-Ādeveloper projects
Not required for COS 217, but good to know!
See Appendix 2 for details
39
Maintaining Old Versions
Approach 3: Use CVS, Subversion, Git, ā¦ā¢ High-Āpowered version control systemsā¢ Appropriate for multi-Ādeveloper projectsā¢ Allow repositories to be shared
Beyond our scope, but good to know!
Summary
General debugging strategies and tools:(1) Understand error messages(2) Think before writing(3) Look for common bugs(4) Divide and conquer(5) Add more internal tests(6) Display output(7) Use a debuggerā¢ Use GDB!!!
(8) Focus on recent changesā¢ Consider using RCS, etc.
40
41
Appendix 1: Using GDBAn example programFile testintmath.c:
#include <stdio.h>
int gcd(int i, int j) int temp;
while (j != 0) temp = i % j;
i = j; j = temp;
return i;
int lcm(int i, int j) return (i / gcd(i, j)) * j; ā¦
The program is correct
But letās pretend it has a runtime error in gcd()ā¦
ā¦int main(void) int iGcd;
int iLcm; iGcd = gcd(8, 12); iLcm = lcm(8, 12); printf("%d %d\n", iGcd, iLcm); return 0;
Euclidās algorithm;;Donāt be concernedwith details
42
Appendix 1: Using GDB
General GDB strategy:
ā¢ Execute the program to the point of interestā¢ Use breakpoints and stepping to do that
ā¢ Examine the values of variables at that point
43
Appendix 1: Using GDBTypical steps for using GDB:
(a) Build with āggcc217 āg testintmath.c āo testintmath
ā¢ Adds extra information to executable file that GDB uses(b) Run Emacs, with no arguments
emacs
(c) Run GDB on executable file from within Emacs<Esc key> x gdb <Enter key> testintmath <Enter key>
(d) Set breakpoints, as desired
break mainā¢ GDB sets a breakpoint at the first executable line of main()
break gcdā¢ GDB sets a breakpoint at the first executable line of gcd()
44
Appendix 1: Using GDBTypical steps for using GDB (cont.):(e) Run the program
runā¢ GDB stops at the breakpoint in main()ā¢ Emacs opens window showing source codeā¢ Emacs highlights line that is to be executed nextcontinueā¢ GDB stops at the breakpoint in gcd()ā¢ Emacs highlights line that is to be executed next
(f) Step through the program, as desiredstep (repeatedly)ā¢ GDB executes the next line (repeatedly)
ā¢ Note: When next line is a call of one of your functions:ā¢ step command steps into the functionā¢ next command steps over the function, that is, executes the next line without stepping into the function
45
Appendix 1: Using GDBTypical steps for using GDB (cont.):
(g) Examine variables, as desiredprint iprint jprint temp
ā¢ GDB prints the value of each variable(h) Examine the function call stack, if desired
where
ā¢ GBB prints the function call stackā¢ Useful for diagnosing crash in large program
(i) Exit gdbquit
(j) Exit Emacs<Ctrl-x key> <Ctrl-c key>
46
Appendix 1: Using GDB
GDB can do much more:ā¢ Handle command-Āline arguments
run arg1 arg2
ā¢ Handle redirection of stdin, stdout, stderrrun < somefile > someotherfile
ā¢ Print values of expressionsā¢ Break conditionallyā¢ Etc.
47
Appendix 2: Using RCSTypical steps for using RCS:(a) Create project directory, as usual
mkdir helloprojcd helloproj
(b) Create RCS directory in project directorymkdir RCS
ā¢ RCS will store its repository in that directory(c) Create source code files in project directory
emacs hello.c ā¦
(d) Check inci hello.c
ā¢ Adds file to RCS repositoryā¢ Deletes local copy (donāt panic!)ā¢ Can provide description of file (1st time)ā¢ Can provide log message, typically describing changes
48
Appendix 2: Using RCSTypical steps for using RCS (cont.):(e) Check out most recent version for reading
co hello.c
ā¢ Copies file from repository to project directoryā¢ File in project directory has read-Āonly permissions
(f) Check out most recent version for reading/writingco āl hello.c
ā¢ Copies file from repository to project directoryā¢ File in project directory has read/write permissions
(g) List versions in repositoryrlog hello.c
ā¢ Shows versions of file, by number (1.1, 1.2, etc.), with descriptions
(h) Check out a specified versionco āl ārversionnumber hello.c
49
Appendix 2: Using RCS
RCS can do much more:ā¢ Merge versions of filesā¢ Maintain distinct development branchesā¢ Place descriptions in code as commentsā¢ Assign symbolic names to versionsā¢ Etc.
Recommendation: Use RCSā¢ ci and co can become automatic!