240-491 Adv. UNIX: debug/141 Advanced UNIX v Objectives of these slides: –tools and techniques for...
-
Upload
natalie-bridges -
Category
Documents
-
view
215 -
download
0
Transcript of 240-491 Adv. UNIX: debug/141 Advanced UNIX v Objectives of these slides: –tools and techniques for...
240-491 Adv. UNIX: debug/14 1
Advanced UNIXAdvanced UNIX
Objectives of these slides:Objectives of these slides:– tools and techniques for debugging C codetools and techniques for debugging C code
240-491 Special Topics in Comp. Eng. 1Semester 2, 2000-2001
14. Debugging
240-491 Adv. UNIX: debug/14 2
OverviewOverview
1.1. What is Debugging? What is Debugging?
2.2. Catching Errors at Compile Time Catching Errors at Compile Time
3. Debugging with 3. Debugging with printf()printf()'s's
4. Conditional Compilation4. Conditional Compilation
5. 5. assert()assert()
6. 6. gdbgdb
7. Memory Leaks7. Memory Leaks
8. More Information8. More Information
240-491 Adv. UNIX: debug/14 3
1. What is Debugging?1. What is Debugging?
Debugging is the process of Debugging is the process of locatinglocating and and removingremoving errors. errors.
It has been estimated that It has been estimated that 85%85% of debugging of debugging time is spent locating errors and only time is spent locating errors and only 15%15% spent fixing themspent fixing them– tools that speed up locating are very usefultools that speed up locating are very useful
240-491 Adv. UNIX: debug/14 4
Common C Coding MistakesCommon C Coding Mistakes Array index out of boundsArray index out of bounds
Unintended side effects Unintended side effects – e.g. e.g. a = ba = b instead of instead of a == ba == b
Use of uninitialised variablesUse of uninitialised variables
casecase fall-through in a fall-through in a switchswitch
continued
240-491 Adv. UNIX: debug/14 5
Pointers (memory leaks)Pointers (memory leaks)
Reversed logic in conditions Reversed logic in conditions e.g. e.g. x < 5x < 5 rather than rather than x > 5x > 5
MacrosMacros
Unterminated commentsUnterminated comments
240-491 Adv. UNIX: debug/14 6
2. Catching Errors at Compile Time2. Catching Errors at Compile Time
Use the Use the -Wall-Wall option of option of gccgcc::$ gcc $ gcc -Wall-Wall -o example example.c -o example example.c
Extra warnings include:Extra warnings include:– not using a locally defined variablenot using a locally defined variable– not declaring a functionnot declaring a function
240-491 Adv. UNIX: debug/14 7
Example: useWall.cExample: useWall.c
int main(){ int a, b; int x1, x2;
if (a = b) printf("%d\n", x1); return 0;}
240-491 Adv. UNIX: debug/14 8
$ gcc -o useWall useWall.c$ useWall1074729080
$ gcc -Wall -o useWall useWall.cuseWall.c: In function `main':useWall.c:9: warning: suggest parentheses around assignment used as truth valueuseWall.c:10: warning: implicit declaration of function `printf'useWall.c:7: warning: unused variable `x2'
$ useWall1074729080
Three warnings,along with linenumbers.
240-491 Adv. UNIX: debug/14 9
Finding Line 10 in vi Finding Line 10 in vi
Use Use <number>G<number>G::– e.g.e.g. 10G10G
or:or: Switch on line numbering in Switch on line numbering in vivi::
– :set nu:set nu
– :set nonu:set nonu /* to switch it off *//* to switch it off */
240-491 Adv. UNIX: debug/14 10
3. Debugging with 3. Debugging with printf()printf()ss
Good places to add them in your code:Good places to add them in your code:– at the start of a functionat the start of a function
to print input parametersto print input parameters
– at the return point of a functionat the return point of a function to print output parameters and the return valueto print output parameters and the return value
– at the start of a loopat the start of a loop print the loop counterprint the loop counter
continued
240-491 Adv. UNIX: debug/14 11
printf()s must identify where they are in the code:– e.g. print the function name, line number, as
well as data values– use __LINE__, and others
printf()s should be conditional– see the next section
240-491 Adv. UNIX: debug/14 12
Example: dprintf.c Example: dprintf.c
#include <stdio.h>
int main(){ int x = 5;
printf("Compiled: %s %s\n", __DATE__, __TIME__);
printf("%s/main.%d: x=%d\n",__FILE__, __LINE__, x);
printf("hello world, x=%d\n", x); return 0;}
240-491 Adv. UNIX: debug/14 13
$ gcc -Wall -o dprintf dprintf.c
$ dprintfCompiled: Dec 6 2000 10:27:44dprintf.c/main.11: x=5hello world, x=5
the debugging printf is located by program/function.line number
240-491 Adv. UNIX: debug/14 14
4. Conditional Compilation4. Conditional Compilation
Debugging Debugging printf()printf()s can be 'switched off' s can be 'switched off' by putting comments around themby putting comments around them– but adding comments takes a lot of timebut adding comments takes a lot of time
Conditional compilationConditional compilation: selectively : selectively compile portions of the programcompile portions of the program– conditional compilation can be used to select conditional compilation can be used to select
which which printf()printf()s to include in the compilations to include in the compilation
240-491 Adv. UNIX: debug/14 15
Example: cinfo.cExample: cinfo.c #include <stdio.h>
int main(){ int x = 5;
#ifdef DEBUG printf("Compiled: %s %s\n",
__DATE__, __TIME__); printf("%s/main.%d: x=%d\n",
__FILE__, __LINE__, x);#endif
printf("hello world, x=%d\n", x); return 0;}
240-491 Adv. UNIX: debug/14 16
$ gcc -Wall -o cinfo cinfo.c$ gcc -Wall -o cinfo cinfo.c
$ cinfo$ cinfohello world, x=5hello world, x=5
$ gcc -Wall -o cinfo cinfo.c $ gcc -Wall -o cinfo cinfo.c -DDEBUG-DDEBUG
$ cinfo$ cinfoCompiled: Dec 6 2000 10:39:14Compiled: Dec 6 2000 10:39:14cinfo.c/main.15: x=5cinfo.c/main.15: x=5hello world, x=5hello world, x=5
define theDEBUG constant
240-491 Adv. UNIX: debug/14 17
Harder Debug SwitchingHarder Debug Switching
Instead of having the Instead of having the -D-D option on the option on the command line, the constant can be defined command line, the constant can be defined inside the program:inside the program:
#define DEBUG#define DEBUG
This is more work.This is more work.
240-491 Adv. UNIX: debug/14 18
Fancier #if: ifsdebug.cFancier #if: ifsdebug.c#include <stdio.h>int main(){ int n1 = 1, n2 = 2, n3 = 3; #if TESTFLAG == 1 printf("main: n1=%d\n", n1);#elif TESTFLAG == 2 printf("main: n2=%d\n", n2);#else printf("main: n3=%d\n", n3);#endif
printf("n1=%d, n2=%d, n3=%d\n", n1, n2, n3);
return 0;}
240-491 Adv. UNIX: debug/14 19
$ gcc -Wall -o ifsdebug ifsdebug.c -DTESTFLAG=1$ ifsdebugmain: n1=1n1=1, n2=2, n3=3
$ gcc -Wall -o ifsdebug ifsdebug.c -DTESTFLAG=2$ ifsdebugmain: n2=2n1=1, n2=2, n3=3
$ gcc -Wall -o ifsdebug ifsdebug.c$ ifsdebugmain: n3=3n1=1, n2=2, n3=3
No -D option meansthat TESTFLAG isundefined.
240-491 Adv. UNIX: debug/14 20
5. assert()5. assert()
For testing assertions about the program.For testing assertions about the program.
assert()assert() calls can contain any C expression:calls can contain any C expression:assert(x==y);assert(x==y);assert(ptr != NULL);assert(ptr != NULL);
If the evaluation is 0 (false) at runtime, an If the evaluation is 0 (false) at runtime, an error message is produced, and execution is error message is produced, and execution is aborted.aborted.
240-491 Adv. UNIX: debug/14 21
Example: assertTest.cExample: assertTest.c #include <stdio.h>
#include <math.h>#include <assert.h>
double my_sqrt(double x);
int main(){ printf("sqrt +2 = %g\n", my_sqrt(2.0)); printf("sqrt -2 = %g\n", my_sqrt(-2.0)); return 0;}
double my_sqrt(double x){ assert(x >= 0.0); return sqrt(x);}
240-491 Adv. UNIX: debug/14 22
$ gcc -Wall -o assertTest assertTest.c -lm$ assertTestsqrt +2 = 1.41421assertTest: assertTest.c:20: my_sqrt:
Assertion `x >= 0.0' failed.Aborted
$ gcc -Wall -o assertTest assertTest.c -lm -DNDEBUG
$ assertTestsqrt +2 = 1.41421sqrt -2 = nan$
assert() switched off
"not a number"
240-491 Adv. UNIX: debug/14 23
6. gdb6. gdb gdbgdb is the interactive is the interactive source-level debuggersource-level debugger from from
the GNU Projectthe GNU Project– the debugger allows the programmer to see bugs in the the debugger allows the programmer to see bugs in the
source code as the program executessource code as the program executes
Information on Information on gdbgdb::– $ man gdb$ man gdb– $ gdb -help$ gdb -help– $ info gdb$ info gdb
– type type helphelp when running when running gdbgdb
240-491 Adv. UNIX: debug/14 24
6.1. Main Features6.1. Main Features
Source line steppingSource line stepping Printing/monitoring variablesPrinting/monitoring variables Source-level breakpointsSource-level breakpoints
Analysing core dumpsAnalysing core dumps Graphical interfaces exist (using X)Graphical interfaces exist (using X)
– xxgdbxxgdb
240-491 Adv. UNIX: debug/14 25
6.2. How to use gdb6.2. How to use gdb
1) Compile with the 1) Compile with the -g-g option of option of gccgcc::$ gcc $ gcc -g-g -o examp examp.c -o examp examp.c
2) Execute the object code within 2) Execute the object code within gdbgdb::$ $ gdbgdb examp examp
240-491 Adv. UNIX: debug/14 26
6.3. gdb and Crashing Code6.3. gdb and Crashing Code include <stdio.h>
void foo(int *px);void bar(int *px);
int main(){ int *px; px = (int *) 1000; /* px is address 1000 */ foo(px); return 0;}
void foo(int *px){ bar(px); }
void bar(int *px){ *px = 3; } /* assign 3 into address 1000 */
crash.c
240-491 Adv. UNIX: debug/14 27
$ gcc -Wall -o crash crash.c$ crashSegmentation fault$ gcc -Wall -g -o crash crash.c$ gdb crashGNU gdb. Copyright 1998...(gdb) runStarting program: crash
Program received signal SIGSEGV, Segmentation fault.0x80483f2 in bar (px=0x3e8) at crash.c:2727 *px = 3;(gdb) where#0 0x80483f2 in bar (px=0x3e8) at crash.c:27#1 0x80483e6 in foo (px=0x3e8) at crash.c:22#2 0x80483c9 in main () at crash.c:16(gdb) quitThe program is running. Exit anyway? (y or n) y$
crash crashesat line 27 inbar()
240-491 Adv. UNIX: debug/14 28
6.4. gdb and Non-terminating Code6.4. gdb and Non-terminating Code
1. Start the code:1. Start the code: runrun
2. Wait; interrupt execution:2. Wait; interrupt execution: ctrl-cctrl-c
3. Find location:3. Find location: wherewhere– list <function name>list <function name>
– print <variable name>print <variable name>
4. Step through the code:4. Step through the code: stepstep
240-491 Adv. UNIX: debug/14 29
Example: nonterm.cExample: nonterm.c
include <stdio.h>
int main(){ int num = 1;
while (num > 0) if (num*num > 10000) { printf("Largest n is %d\n", num-1); num++; } return 0;}
240-491 Adv. UNIX: debug/14 30
$ gcc -Wall -g -o nonterm nonterm.c
$ gdb nontermGNU gdb Copyright ...(gdb) runStarting program: nonterm
Program received signal SIGINT, Interrupt.0x8048404 in main () at nonterm.c:1212 if (num*num > 10000) {(gdb) where#0 0x8048404 in main () at nonterm.c:12
:
I typed ctrl-C
240-491 Adv. UNIX: debug/14 31
(gdb) list7 int main()8 {9 int num = 1;1011 while (num > 0)12 if (num*num > 10000) {13 printf("Largest n is %d\n", num-1); 14 num++;15 }16 return 0;(gdb) print num$1 = 1(gdb) contContinuing.
Program received signal SIGINT, Interrupt.main () at nonterm.c:1515 }
:
I typed ctrl-C again
240-491 Adv. UNIX: debug/14 32
(gdb) print num$2 = 1(gdb) step12 if (num*num > 10000) {(gdb) step15 }(gdb) step12 if (num*num > 10000) {(gdb) step15 }(gdb) quitThe program is running. Exit anyway? (y or n) y$
240-491 Adv. UNIX: debug/14 33
Getting indents RightGetting indents Right $ indent -kr nonterm.c -o nonterm2.c
$ cat nonterm2.c#include <stdio.h>
int main(){ int num = 1;
while (num > 0) if (num * num > 10000) { printf("Largest n is %d\n", num - 1); num++; } return 0;}
240-491 Adv. UNIX: debug/14 34
6.5. gdb and Wrong Answers6.5. gdb and Wrong Answers
1)1) ThinkThink about the error about the error before using gdb.before using gdb.
2)2) Put Put breakpointsbreakpoints into the code. into the code.
3)3) Run the code.Run the code.
4)4) At each breakpoint, At each breakpoint, stepstep through the code. through the code.
5)5) PrintPrint variables and variables and listlist code often: code often:
6)6) If the code looks okay, If the code looks okay, continuecontinue execution. execution.
7)7) DeleteDelete breakpoints that are no longer breakpoints that are no longer needed.needed.
240-491 Adv. UNIX: debug/14 35
Example: lowercase.cExample: lowercase.c /* convert input to lowercase */
#include <stdio.h>#include <ctype.h>
#define SIZE 1024
void lower(char lin[]);
int main(){ char line[SIZE]; while (fgets(line, 1024, stdin) != NULL) { lower(line); fputs(line, stdout); } return 0;}
continued
240-491 Adv. UNIX: debug/14 36
void lower(char lin[])/* convert any uppercase letters to lowercase */{ int count = 0;
while (lin[count] != '\0') { if (isupper(lin[count]))/* lin[count] = tolower(lin[count]); */ lin[count] += 34; count++; }}
240-491 Adv. UNIX: debug/14 37
The Debugging ProcessThe Debugging Process
$ gcc -Wall -g -o lowercase lowercase.c$ lowercaseabcdeabcdeAAAAAcccccBBBAAAAdddcccc
$ gdb lowercaseGNU gdb... (gdb) break lowerBreakpoint 1 at 0x80484ee: file lowercase.c, line 28.
:
somethingis wrong
240-491 Adv. UNIX: debug/14 38
(gdb) runStarting program: lowercase AAAAA
Breakpoint 1, lower (lin=0xbffff8fc "AAAAA\n") at lowercase.c:28
28 int count = 0;(gdb) finishRun till exit from #0 lower (lin=0xbffff8fc
"AAAAA\n") at lowercase.c:280x80484c4 in main () at lowercase.c:1717 lower(line);(gdb) print line[0]@10$1 = "ccccc\n\000\000\000"
:
typed in by me
240-491 Adv. UNIX: debug/14 39
(gdb) info breakNum Type Disp Enb Address What1 breakpoint keep y 0x080484ee in
lower at lowercase.c:28breakpoint already hit 1 time
(gdb) delete 1(gdb) list 3328 int count = 0;2930 while (lin[count] != '\0') {31 if (isupper(lin[count]))32 /* lin[count] = tolower(lin[count]); */33 lin[count] += 34;34 count++;35 }36 }37
:
240-491 Adv. UNIX: debug/14 40
(gdb) break 33Breakpoint 2 at 0x8048526: file lowercase.c, line 33.(gdb) contContinuing.cccccBBBBAAAA
Breakpoint 2, lower (lin=0xbffff8fc "BBBBAAAA\n") at lowercase.c:3333 lin[count] += 34;(gdb) step34 count++;(gdb) print lin[0]@10$2 = "dBBBAAAA\n"(gdb) quitThe program is running. Exit anyway? (y or n) y$
typed in by me
240-491 Adv. UNIX: debug/14 41
7. Memory Leaks7. Memory Leaks
Dynamic data created with Dynamic data created with malloc()malloc() is is not checked when it is usednot checked when it is used– it is easy for a programmer to assign data it is easy for a programmer to assign data
outside the malloc'ed areaoutside the malloc'ed area
– the error will probably not cause a crash until the error will probably not cause a crash until much later when the altered memory is much later when the altered memory is accessed by another part of the programaccessed by another part of the program
continued
240-491 Adv. UNIX: debug/14 42
There are a number of tools which monitor There are a number of tools which monitor the usage of malloc'ed space, and cause an the usage of malloc'ed space, and cause an error if they are used incorrectlyerror if they are used incorrectly– the ElectricFence library (the ElectricFence library (efenceefence))– the the checkergcccheckergcc compiler compiler
240-491 Adv. UNIX: debug/14 43
Example: Example: efTest.cefTest.c
#include <stdio.h>#include <stdlib.h>
int main(){ char *ptr = (char *)malloc(1024); ptr[0] = 0;
/* now write beyond the block */ ptr[1024] = 0; printf("Everything is wondeful (I don't think)\n"); exit(0);}
240-491 Adv. UNIX: debug/14 44
ExecutionExecution
$ gcc -Wall -o efTest efTest.c$ efTestEverything is wondeful (I don't think)
$ gcc -Wall -o efTest efTest.c -lefence$ efTest
Electric Fence 2.0.5 Copyright (C) 1987-1998 Bruce Perens.
Segmentation fault$
continued
240-491 Adv. UNIX: debug/14 45
$ gcc -Wall -g -o efTest efTest.c -lefence$ gdb efTestGNU gdb...(gdb) runStarting program: efTest
Electric Fence 2.0.5 Copyright (C) 1987-1998 Bruce Perens.
Program received signal SIGSEGV, Segmentation fault.
0x80485c9 in main () at efTest.c:1717 ptr[1024] = 0;(gdb) quitThe program is running. Exit anyway? (y or n) y$
240-491 Adv. UNIX: debug/14 46
8. More Information8. More Information
Beginning Linux ProgrammingBeginning Linux ProgrammingNeil Matthew and Rick StonesNeil Matthew and Rick StonesWrox Press, 1996Wrox Press, 1996Chapter 9: DebuggingChapter 9: Debugging