Presentation is loading. Please wait.

Presentation is loading. Please wait.

240-491 Adv. UNIX: debug/141 Advanced UNIX v Objectives of these slides: –tools and techniques for debugging C code 240-491 Special Topics in Comp. Eng.

Similar presentations


Presentation on theme: "240-491 Adv. UNIX: debug/141 Advanced UNIX v Objectives of these slides: –tools and techniques for debugging C code 240-491 Special Topics in Comp. Eng."— Presentation transcript:

1 240-491 Adv. UNIX: debug/141 Advanced UNIX v Objectives of these slides: –tools and techniques for debugging C code 240-491 Special Topics in Comp. Eng. 1 Semester 2, 2000-2001 14. Debugging

2 240-491 Adv. UNIX: debug/142 Overview 1. What is Debugging? 2. Catching Errors at Compile Time 3. Debugging with printf() 's 4. Conditional Compilation 5. assert() 6. gdb 7. Memory Leaks 8. More Information

3 240-491 Adv. UNIX: debug/143 1. What is Debugging? v Debugging is the process of locating and removing errors. v It has been estimated that 85% of debugging time is spent locating errors and only 15% spent fixing them –tools that speed up locating are very useful

4 240-491 Adv. UNIX: debug/144 Common C Coding Mistakes v Array index out of bounds v Unintended side effects –e.g. a = b instead of a == b v Use of uninitialised variables  case fall-through in a switch continued

5 240-491 Adv. UNIX: debug/145 v Pointers (memory leaks)  Reversed logic in conditions e.g. x 5 v Macros v Unterminated comments

6 240-491 Adv. UNIX: debug/146 2. Catching Errors at Compile Time  Use the -Wall option of gcc : $ gcc -Wall -o example example.c v Extra warnings include: –not using a locally defined variable –not declaring a function

7 240-491 Adv. UNIX: debug/147 Example: useWall.c v v int main() { int a, b; int x1, x2; if (a = b) printf("%d\n", x1); return 0; }

8 240-491 Adv. UNIX: debug/148 v v $ gcc -o useWall useWall.c $ useWall 1074729080 $ gcc -Wall -o useWall useWall.c useWall.c: In function `main': useWall.c:9: warning: suggest parentheses around assignment used as truth value useWall.c:10: warning: implicit declaration of function `printf' useWall.c:7: warning: unused variable `x2' $ useWall 1074729080 Three warnings, along with line numbers.

9 240-491 Adv. UNIX: debug/149 Finding Line 10 in vi  Use G : –e.g. 10G or:  Switch on line numbering in vi : –:set nu –:set nonu /* to switch it off */

10 240-491 Adv. UNIX: debug/1410 3. Debugging with printf() s v Good places to add them in your code: –at the start of a function u to print input parameters –at the return point of a function u to print output parameters and the return value –at the start of a loop u print the loop counter continued

11 240-491 Adv. UNIX: debug/1411   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

12 240-491 Adv. UNIX: debug/1412 Example: dprintf.c v v #include 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; }

13 240-491 Adv. UNIX: debug/1413 v v $ gcc -Wall -o dprintf dprintf.c $ dprintf Compiled: Dec 6 2000 10:27:44 dprintf.c/main.11: x=5 hello world, x=5 the debugging printf is located by program/function. line number

14 240-491 Adv. UNIX: debug/1414 4. Conditional Compilation  Debugging printf() s can be 'switched off' by putting comments around them –but adding comments takes a lot of time v Conditional compilation: selectively compile portions of the program –conditional compilation can be used to select which printf() s to include in the compilation

15 240-491 Adv. UNIX: debug/1415 Example: cinfo.c v v #include 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; }

16 240-491 Adv. UNIX: debug/1416 v $ gcc -Wall -o cinfo cinfo.c $ cinfo hello world, x=5 $ gcc -Wall -o cinfo cinfo.c -DDEBUG $ cinfo Compiled: Dec 6 2000 10:39:14 cinfo.c/main.15: x=5 hello world, x=5 define the DEBUG constant

17 240-491 Adv. UNIX: debug/1417 Harder Debug Switching  Instead of having the -D option on the command line, the constant can be defined inside the program: #define DEBUG v This is more work.

18 240-491 Adv. UNIX: debug/1418 Fancier #if: ifsdebug.c #include 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; }

19 240-491 Adv. UNIX: debug/1419 v v $ gcc -Wall -o ifsdebug ifsdebug.c -DTESTFLAG=1 $ ifsdebug main: n1=1 n1=1, n2=2, n3=3 $ gcc -Wall -o ifsdebug ifsdebug.c -DTESTFLAG=2 $ ifsdebug main: n2=2 n1=1, n2=2, n3=3 $ gcc -Wall -o ifsdebug ifsdebug.c $ ifsdebug main: n3=3 n1=1, n2=2, n3=3 No -D option means that TESTFLAG is undefined.

20 240-491 Adv. UNIX: debug/1420 5. assert() v For testing assertions about the program.  assert() calls can contain any C expression: assert(x==y); assert(ptr != NULL); v If the evaluation is 0 (false) at runtime, an error message is produced, and execution is aborted.

21 240-491 Adv. UNIX: debug/1421 Example: assertTest.c v v #include #include #include 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); }

22 240-491 Adv. UNIX: debug/1422 v v $ gcc -Wall -o assertTest assertTest.c -lm $ assertTest sqrt +2 = 1.41421 assertTest: assertTest.c:20: my_sqrt: Assertion `x >= 0.0' failed. Aborted $ gcc -Wall -o assertTest assertTest.c -lm -DNDEBUG $ assertTest sqrt +2 = 1.41421 sqrt -2 = nan $ assert() switched off "not a number"

23 240-491 Adv. UNIX: debug/1423 6. gdb  gdb is the interactive source-level debugger from the GNU Project –the debugger allows the programmer to see bugs in the source code as the program executes  Information on gdb : –$ man gdb –$ gdb -help –$ info gdb –type help when running gdb

24 240-491 Adv. UNIX: debug/1424 6.1. Main Features v Source line stepping v Printing/monitoring variables v Source-level breakpoints v Analysing core dumps v Graphical interfaces exist (using X) –xxgdb

25 240-491 Adv. UNIX: debug/1425 6.2. How to use gdb 1) Compile with the -g option of gcc : $ gcc -g -o examp examp.c 2) Execute the object code within gdb : $ gdb examp

26 240-491 Adv. UNIX: debug/1426 6.3. gdb and Crashing Code v v include 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

27 240-491 Adv. UNIX: debug/1427 v v $ gcc -Wall -o crash crash.c $ crash Segmentation fault $ gcc -Wall -g -o crash crash.c $ gdb crash GNU gdb. Copyright 1998... (gdb) run Starting program: crash Program received signal SIGSEGV, Segmentation fault. 0x80483f2 in bar (px=0x3e8) at crash.c:27 27 *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) quit The program is running. Exit anyway? (y or n) y $ crash crashes at line 27 in bar()

28 240-491 Adv. UNIX: debug/1428 6.4. gdb and Non-terminating Code 1. Start the code: run 2. Wait; interrupt execution: ctrl-c 3. Find location: where –list –list –print –print 4. Step through the code: step

29 240-491 Adv. UNIX: debug/1429 Example: nonterm.c v v include int main() { int num = 1; while (num > 0) if (num*num > 10000) { printf("Largest n is %d\n", num-1); num++; } return 0; }

30 240-491 Adv. UNIX: debug/1430 v v $ gcc -Wall -g -o nonterm nonterm.c $ gdb nonterm GNU gdb Copyright... (gdb) run Starting program: nonterm Program received signal SIGINT, Interrupt. 0x8048404 in main () at nonterm.c:12 12 if (num*num > 10000) { (gdb) where #0 0x8048404 in main () at nonterm.c:12 : I typed ctrl-C

31 240-491 Adv. UNIX: debug/1431 (gdb) list 7 int main() 8 { 9 int num = 1; 10 11 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) cont Continuing. Program received signal SIGINT, Interrupt. main () at nonterm.c:15 15 } : I typed ctrl-C again

32 240-491 Adv. UNIX: debug/1432 v v (gdb) print num $2 = 1 (gdb) step 12 if (num*num > 10000) { (gdb) step 15 } (gdb) step 12 if (num*num > 10000) { (gdb) step 15 } (gdb) quit The program is running. Exit anyway? (y or n) y $

33 240-491 Adv. UNIX: debug/1433 Getting indents Right v v $ indent -kr nonterm.c -o nonterm2.c $ cat nonterm2.c #include int main() { int num = 1; while (num > 0) if (num * num > 10000) { printf("Largest n is %d\n", num - 1); num++; } return 0; }

34 240-491 Adv. UNIX: debug/1434 6.5. gdb and Wrong Answers 1)Think about the error before using gdb. 2)Put breakpoints into the code. 3)Run the code. 4)At each breakpoint, step through the code. 5)Print variables and list code often: 6)If the code looks okay, continue execution. 7)Delete breakpoints that are no longer needed.

35 240-491 Adv. UNIX: debug/1435 Example: lowercase.c v v /* convert input to lowercase */ #include #include #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

36 240-491 Adv. UNIX: debug/1436 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++; } }

37 240-491 Adv. UNIX: debug/1437 The Debugging Process v v $ gcc -Wall -g -o lowercase lowercase.c $ lowercase abcde abcde AAAAA ccccc BBBAAAA dddcccc $ gdb lowercase GNU gdb... (gdb) break lower Breakpoint 1 at 0x80484ee: file lowercase.c, line 28. : something is wrong

38 240-491 Adv. UNIX: debug/1438 (gdb) run Starting program: lowercase AAAAA Breakpoint 1, lower (lin=0xbffff8fc "AAAAA\n") at lowercase.c:28 28 int count = 0; (gdb) finish Run till exit from #0 lower (lin=0xbffff8fc "AAAAA\n") at lowercase.c:28 0x80484c4 in main () at lowercase.c:17 17 lower(line); (gdb) print line[0]@10 $1 = "ccccc\n\000\000\000" : typed in by me

39 240-491 Adv. UNIX: debug/1439 (gdb) info break Num Type Disp Enb Address What 1 breakpoint keep y 0x080484ee in lower at lowercase.c:28 breakpoint already hit 1 time (gdb) delete 1 (gdb) list 33 28 int count = 0; 29 30 while (lin[count] != '\0') { 31 if (isupper(lin[count])) 32/* lin[count] = tolower(lin[count]); */ 33 lin[count] += 34; 34 count++; 35 } 36} 37 :

40 240-491 Adv. UNIX: debug/1440 (gdb) break 33 Breakpoint 2 at 0x8048526: file lowercase.c, line 33. (gdb) cont Continuing. ccccc BBBBAAAA Breakpoint 2, lower (lin=0xbffff8fc "BBBBAAAA\n") at lowercase.c:33 33 lin[count] += 34; (gdb) step 34 count++; (gdb) print lin[0]@10 $2 = "dBBBAAAA\n" (gdb) quit The program is running. Exit anyway? (y or n) y $ typed in by me

41 240-491 Adv. UNIX: debug/1441 7. Memory Leaks  Dynamic data created with malloc() is not checked when it is used –it is easy for a programmer to assign data outside the malloc'ed area –the error will probably not cause a crash until much later when the altered memory is accessed by another part of the program continued

42 240-491 Adv. UNIX: debug/1442 v There are a number of tools which monitor the usage of malloc'ed space, and cause an error if they are used incorrectly –the ElectricFence library ( efence ) –the checkergcc compiler

43 240-491 Adv. UNIX: debug/1443 Example: efTest.c v v #include #include 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); }

44 240-491 Adv. UNIX: debug/1444 Execution v v $ gcc -Wall -o efTest efTest.c $ efTest Everything 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

45 240-491 Adv. UNIX: debug/1445 $ gcc -Wall -g -o efTest efTest.c -lefence $ gdb efTest GNU gdb... (gdb) run Starting 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:17 17 ptr[1024] = 0; (gdb) quit The program is running. Exit anyway? (y or n) y $

46 240-491 Adv. UNIX: debug/1446 8. More Information v Beginning Linux Programming Neil Matthew and Rick Stones Wrox Press, 1996 Chapter 9: Debugging


Download ppt "240-491 Adv. UNIX: debug/141 Advanced UNIX v Objectives of these slides: –tools and techniques for debugging C code 240-491 Special Topics in Comp. Eng."

Similar presentations


Ads by Google