0% found this document useful (0 votes)
13 views49 pages

08 Debugging1

This document discusses debugging techniques. It begins with understanding error messages and thinking carefully before making changes. Common bugs are discussed like off-by-one errors in loops. The technique of divide and conquer debugging is introduced, which involves either removing parts of the input to find the minimal case that causes the bug, or adding parts back in to find the specific addition that introduced the bug.

Uploaded by

panujyne
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views49 pages

08 Debugging1

This document discusses debugging techniques. It begins with understanding error messages and thinking carefully before making changes. Common bugs are discussed like off-by-one errors in loops. The technique of divide and conquer debugging is introduced, which involves either removing parts of the input to find the minimal case that causes the bug, or adding parts back in to find the specific addition that introduced the bug.

Uploaded by

panujyne
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 49

Debugging (Part 1)

The material for this lecture is drawn, in part, from!


The Practice of Programming (Kernighan & Pike) Chapter 5!
1
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 Kernighan
2
For Your Amusement

The first computer bug


(found in the Harvard Mark II computer) 3
“Programming in the Large” Steps
Design & 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
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

5
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?

6
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
Understand Error Messages
Debugging 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 What are the
return 0.
errors? (No
int main(void)
{ printf("hello, world\n"); fair looking at
return 0; the next slide!)
}

8
Understand Error Messages

#include <stdioo.h>
/* Print "hello, world" to stdout and
return 0. Which tool
int main(void) (preprocessor,
{ printf("hello, world\n"); compiler, or
return 0; linker) reports
}
the error(s)?

$ gcc217 hello.c -o hello


hello.c:1:20: error: stdioo.h: No such file or
directory
hello.c:2:1: error: unterminated comment
hello.c:7: warning: ISO C forbids an empty
translation unit

9
Understand Error Messages

#include <stdio.h>
/* Print "hello, world" to stdout and
return 0. */ What are the
int main(void) errors? (No
{ printf("hello, world\n") fair looking at
return 0;
} the next slide!)

10
Understand Error Messages

#include <stdio.h>
/* Print "hello, world" to stdout and
Which tool
return 0. */
int main(void) (preprocessor,
{ printf("hello, world\n") compiler, or
return 0; linker) reports
}
the error?

$ gcc217 hello.c -o hello


hello.c: In function 'main':
hello.c:6: error: expected ';' before 'return'

11
Understand Error Messages

#include <stdio.h>
/* Print "hello, world" to stdout and
return 0. */ What are the
int main(void) errors? (No
{ prinf("hello, world\n"); fair looking at
return 0;
} the next slide!)

12
Understand Error Messages

#include <stdio.h>
/* Print "hello, world" to stdout and Which tool
return 0. */ (preprocessor,
int main(void)
{ prinf("hello, world\n")
compiler, or
return 0; linker) reports
} the error?

$ gcc217 hello.c -o hello


hello.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

13
Understand Error Messages

#include <stdio.h>
#include <stdlib.h>
enum StateType What are the
{ STATE_REGULAR, errors? (No
STATE_INWORD fair looking at
}
int main(void) the next slide!)
{ printf("just hanging around\n");
return EXIT_SUCCESS;
}

14
Understand Error Messages

#include <stdio.h>
#include <stdlib.h>
enum StateType
{ STATE_REGULAR, What does
STATE_INWORD this error
} message even
int main(void)
{ printf("just hanging around\n");
mean?
return EXIT_SUCCESS;
}

$ gcc217 hello.c -o hello


hello.c:7: error: two or more data types in declaration specifiers
hello.c:7: warning: return type of 'main' is not 'int'

15
Understand Error Messages
Caveats 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

16
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
Think Before Writing
Inappropriate 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

18
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
Look for Common Bugs
Some of our favorites:
int i;

switch (i) scanf("%d", i);
{ case 0:
… char c;
break; …
case 1: c = getchar();

case 2:
… while (c = getchar() != EOF)
} …

if (i = 5)

What are
the
if (5 < i < 10) if (i & j)
… …
errors?

20
Look for Common Bugs
Some of our favorites:

for (i = 0; i < 10; i++)


{ for (j = 0; j < 10; i++)
{ ...
}
}
What are
for (i = 0; i < 10; i++) the
{ for (j = 10; j >= 0; j++) errors?
{ ...
}
}

21
Look for Common Bugs
Some of our favorites:

{ int i;

i = 5; What value is
if (something) written if this
{ int i;
statement is

i = 6; present? Absent?

}

printf("%d\n", i);

}

22
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
Divide and Conquer
Divide and conquer: To debug a program…

•  Incrementally find smallest input file that illustrates the bug

•  Approach 1: Remove input


•  Start with file
•  Incrementally remove lines
until bug disappears
•  Examine most-recently-removed lines

•  Approach 2: Add input


•  Start with small subset of file
•  Incrementally add lines
until bug appears
•  Examine most-recently-added lines
24
Divide and Conquer
Divide 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

25
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
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 invariants
can eliminate some functions from the bug hunt

27
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
Display Output
Write values of important variables at critical spots

•  Poor: stdout is buffered;


printf("%d", keyvariable); program may crash
before output appears

•  Maybe better: Printing '\n' flushes


the stdout buffer, but
printf("%d\n", keyvariable);
not if stdout is
redirected to a file
•  Better:
Call fflush() to flush
printf("%d", keyvariable); stdout buffer
fflush(stdout);
explicitly
29
Display Output
Write debugging
output to stderr;
debugging output
•  Maybe even better:
can be separated
fprintf(stderr, "%d", keyvariable); from normal output
via redirection

•  Maybe better still: Bonus: stderr is


unbuffered
FILE *fp = fopen("logfile", "w");

fprintf(fp, "%d", keyvariable); Write to a log file
fflush(fp);

30
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
Use a Debugger

Use a debugger

•  Alternative to displaying output

32
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
33
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
Focus on Recent Changes
Focus on recent changes

•  Corollary: Debug now, not later

Difficult: Easier:

(1) Compose entire program (1) Compose a little


(2) Test entire program (2) Test a little
(3) Debug entire program (3) Debug a little
(4) Compose a little
(5) Test a little
(6) Debug a little

35
Focus on Recent Changes
Focus on recent change (cont.)

•  Corollary: Maintain old versions

Difficult: Easier:

(1) Change code (1) Backup current version


(2) Note new bug (2) Change code
(3) Try to remember what (3) Note new bug
changed since last (4) Compare code with
version last version to
determine what changed

36
Maintaining Old Versions
To 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.


37
Maintaining Old Versions

Approach 2: Use the Revision Control System (RCS)


•  A simple version control system
•  Provided with many Linux distributions
•  Available on nobel
•  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
38
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!

39
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
Appendix 1: Using GDB
An example program Euclid’s algorithm;
File testintmath.c: Don’t be concerned
with details
#include <stdio.h>

int gcd(int i, int j) int main(void)
{ int temp; { int iGcd;
while (j != 0) int iLcm;
{ temp = i % j; iGcd = gcd(8, 12);
i = j; iLcm = lcm(8, 12);
j = temp; printf("%d %d\n", iGcd, iLcm);
return 0;
}
return i; }
}
The program is correct
int lcm(int i, int j)
{ return (i / gcd(i, j)) * j;
} But let’s pretend it has a
… runtime error in gcd()…
41
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

42
Appendix 1: Using GDB
Typical steps for using GDB:

(a) Build with –g


gcc217 –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()
43
Appendix 1: Using GDB
Typical 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 next
continue
•  GDB stops at the breakpoint in gcd()
•  Emacs highlights line that is to be executed next
(f) Step through the program, as desired
step (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
44
Appendix 1: Using GDB
Typical steps for using GDB (cont.):

(g) Examine variables, as desired


print i
print j
print 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 gdb
quit
(j) Exit Emacs
<Ctrl-x key> <Ctrl-c key>
45
Appendix 1: Using GDB

GDB can do much more:


•  Handle command-line arguments
run arg1 arg2
•  Handle redirection of stdin, stdout, stderr
run < somefile > someotherfile
•  Print values of expressions
•  Break conditionally
•  Etc.

46
Appendix 2: Using RCS
Typical steps for using RCS:
(a) Create project directory, as usual
mkdir helloproj
cd helloproj
(b) Create RCS directory in project directory
mkdir RCS
•  RCS will store its repository in that directory
(c) Create source code files in project directory
emacs hello.c …
(d) Check in
ci 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
47
Appendix 2: Using RCS
Typical 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/writing
co –l hello.c
•  Copies file from repository to project directory
•  File in project directory has read/write permissions
(g) List versions in repository
rlog hello.c
•  Shows versions of file, by number (1.1, 1.2, etc.), with
descriptions
(h) Check out a specified version
co –l –rversionnumber hello.c
48
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!

49

You might also like