CSC 2400: Computer Systems Debugging C Programs Slides by Jennifer - - PowerPoint PPT Presentation

csc 2400 computer systems
SMART_READER_LITE
LIVE PREVIEW

CSC 2400: Computer Systems Debugging C Programs Slides by Jennifer - - PowerPoint PPT Presentation

CSC 2400: Computer Systems Debugging C Programs Slides by Jennifer Rexford from Princeton University, slightly modified by Mirela Damian. Goals of this Lecture Help you learn about: ! Strategies for debugging your code ! The GDB debugger


slide-1
SLIDE 1

CSC 2400: Computer Systems

Debugging C Programs

Slides by Jennifer Rexford from Princeton University, slightly modified by Mirela Damian.

slide-2
SLIDE 2

Goals of this Lecture

  • Help you learn about:

! Strategies for debugging your code ! The GDB debugger

  • 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

2

slide-3
SLIDE 3

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?

3

slide-4
SLIDE 4

Debugging Heuristics

Debugging Heuristic When Applicable (1) Understand error messages Build-time (2) Look for familiar bugs Run-time (3) Display output (4) Use a debugger (5) Focus on recent changes

4

slide-5
SLIDE 5

Understand Error Messages

Debugging at build-time is easier than debugging at run- time, if and only if you… (1) Understand the error messages!!!

! Some are from the preprocessor

5

#include <stdioo.h> int main(void) /* Print "hello, world" to stdout and return 0. { printf("hello, world\n"); return 0; } $ gcc hello.c -o hello hello.c:1:20: stdioo.h: No such file or directory hello.c:3:1: unterminated comment hello.c:2: error: syntax error at end of input

Misspelled #include file Missing */

slide-6
SLIDE 6

Understand Error Messages (cont.)

(1) Understand the error messages (cont.)

! Some are from the compiler

6

#include <stdio.h> int main(void) /* Print "hello, world" to stdout and return 0. */ { printf("hello, world\n") retun 0; }

$ gcc hello.c -o hello hello.c: In function `main': hello.c:7: error: `retun' undeclared (first use in this function) hello.c:7: error: (Each undeclared identifier is reported only once hello.c:7: error: for each function it appears in.) hello.c:7: error: syntax error before numeric constant

Misspelled keyword

slide-7
SLIDE 7

Understand Error Messages (cont.)

(1) Understand error messages (cont.)

! Some are from the linker

7

#include <stdio.h> int main(void) /* Print "hello, world" to stdout and return 0. */ { prinf("hello, world\n") return 0; }

$ gcc hello.c -o hello hello.c: In function `main': hello.c:6: warning: implicit declaration of function `prinf' /tmp/cc43ebjk.o(.text+0x25): In function `main': : undefined reference to `prinf' collect2: ld returned 1 exit status

Misspelled function name Compiler warning (not error): prinf() is called before declared Linker error: Cannot find definition of prinf()

slide-8
SLIDE 8

Look for Familiar Bugs

(2) Look for familiar bugs

! Some of our favorites:

8

int i; … scanf("%d", i); char c; … c = getchar(); switch (i) { case 0: … /* missing break */ case 1: … break; … } if (i = 5) … if (5 < i < 10) … if (i & j) … while (c = getchar() != EOF) …

Note: enabling warnings will catch some (but not all) of these

slide-9
SLIDE 9

Display Output

(3) Display output

! Print values of important variables at critical spots ! Poor: ! Maybe better: ! Better:

9

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

slide-10
SLIDE 10

Display Output (cont.)

(3) Display output (cont.)

! Maybe even better: ! Maybe better still:

10

fprintf(stderr, "%d", keyvariable); FILE *fp = fopen("logfile", "w"); … fprintf(fp, "%d", keyvariable); fflush(fp);

Write debugging

  • utput to stderr;

debugging output can be separated from normal output via redirection Write to a log file Bonus: stderr is unbuffered

slide-11
SLIDE 11

Use a Debugger

(4) Use a debugger ! Bugs often are the result of a flawed mental model; debugger can help correct mental model ! Sometimes (but not always) debugger is more convenient than inserting printing statements ! Debugger can load “core dumps” and let you step through state of program when it died ! Can “attach” to running programs to examine execution

  • The GDB Debugger

! Part of the GNU development environment ! Integrated with the EMACS editor

11

slide-12
SLIDE 12

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

12

slide-13
SLIDE 13

Using GDB (cont.)

  • Typical steps for using GDB:

(1) Build with –g

gcc –g testintmath.c –o testintmath

  • Adds extra information to executable file that GDB uses

(2) Run GDB on executable file

gdb ./testintmath

(3) 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()

13

slide-14
SLIDE 14

Using GDB (cont.)

  • Typical steps for using GDB (cont.):

(4) Run the program

run

  • GDB stops at the breakpoint in main()

continue

  • GDB stops at the breakpoint in gcd()

(5) 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

14

slide-15
SLIDE 15

Using GDB (cont.)

  • Typical steps for using GDB (cont.):

(6) Examine variables, as desired

print i print j print temp

  • GDB prints the value of each variable

(7) Examine the function call stack, if desired

where

  • GDB prints the function call stack
  • Useful for diagnosing crash in large program

(8) Exit gdb

quit

15

slide-16
SLIDE 16

Using GDB (cont.)

  • Formatted printing:

print /x i (print the contents of i in hexadecimal) print /t i (print the contents of i in binary) print /d i (print the contents of i in decimal) print /c i (print the contents of i as a character)

16

slide-17
SLIDE 17

Using GDB (cont.)

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

17

slide-18
SLIDE 18

Focus on Recent Changes

(5) Focus on recent changes

! Corollary: Debug now, not later – Difficult: Write entire program; test entire program; debug entire program – Easier: Write a little; test a little; debug a little; write a little; test a little; debug a little; … ! Corollary: Maintain previous versions – Difficult: Change code; note bug; try to remember what changed since last working version!!! – Easier: Backup code; change code; note bug; compare new version with last working version to determine what changed

18

slide-19
SLIDE 19

Maintaining Previous Versions

  • To maintain previous versions

! Approach 1: Manually copy project directory – Repeat occasionally

19

… $ mkdir myproject $ cd myproject Create project files here. $ cd .. $ cp –r myproject myprojectDateTime $ cd myproject Continue creating project files here. …

slide-20
SLIDE 20

Summary

Debugging Heuristic When Applicable (1) Understand error messages Build-time (2) Look for familiar bugs Run-time (3) Display output (4) Use a debugger * (5) Focus on recent changes

20

* Use GDB