Presentation is loading. Please wait.

Presentation is loading. Please wait.

Debugger Ritu Chaturvedi 60-321.

Similar presentations


Presentation on theme: "Debugger Ritu Chaturvedi 60-321."— Presentation transcript:

1 Debugger Ritu Chaturvedi

2 Objectives Background Basic C issues Tools and Techniques Programs
Ritu Chaturvedi

3 Debug !! If it ain’t broke, don’t fix it. Ronald Reagan
If we can’t fix it, it ain’t broke.             Lt. Col. Walter Weir Ritu Chaturvedi

4 Noticing and Understanding bugs
Before you can debug, you need bugs!  How can you tell if your code is buggy?  You need testing! Ritu Chaturvedi

5 Types of bugs What kinds of bugs are there? Syntax errors Build errors
Caught by the compiler Build errors Makefiles can help Semantic errors Uninitialized variables, dead code, typing wrong variables, pointer errors Ritu Chaturvedi

6 Common C errors Common C errors result from: Preprocessing
Macro expansion System dependencies System call availability and definitions Size and representation of types, use sizeof() Explicit memory management Using unallocated or deallocated memory Name space issues Use static keyword, minimize use of globals Ritu Chaturvedi

7 Debugging techniques Techniques include (but are not limited to):
Compiler features Warnings (-Wtype) Optimizations (-Ox) printf() debugging Assertions Code walkthrough Debugging tools Ritu Chaturvedi

8 printf() debugging Very common, but there are disadvantages:
Output is relatively very slow Ad-hoc code addition and removal stdout is buffered and may be lost Solutions: Use macros to encapsulate debug printf’s Use stderr for debugging output Ritu Chaturvedi

9 printf() debugging Use macros to encapsulate debug printf’s
#include <stdio.h> #define DEBUG // or use cc –DDEBUG filename.c int main(){ int i, nread; nread = scanf("%d", &i); #ifdef DEBUG printf("Number of integers read = %d \n", nread); printf("i=%d \n", i); #endif return 0; } Ritu Chaturvedi

10 Assertions The verb "assert" has 4 senses literally
1. assert, maintain -- (state categorically) 2. affirm, verify, assert, avow, aver, swan, swear -- (to declare or affirm solemnly and formally as true; "Before God I swear I am innocent") 3. assert, put forward -- (insist on having one's opinions and rights recognized; "Women should assert themselves more!") 4. insist, assert -- (assert to be true; "The letter asserts a free society") When a programmer writes an assert statement he's saying, 'this condition must be true or we have an error'. Ritu Chaturvedi

11 Assertions - Always assert that your code is right !
An assertion is a predicate (i.e., a true–false statement) placed in a program to indicate that the developer thinks that the predicate is always true at that place. When should you assert ? whenever you can use it to verify the truth of a situation: this pointer can never be null this number is never smaller than zero this number has to be in the range of 10 and 30 Ritu Chaturvedi

12 Assertions Header <assert.h> Macro assert()
Tests value of an expression If 0 (false) prints error message and calls abort Example: assert( x <= 10 ); If x is not <= 10, the program will print an error message and abort. Ritu Chaturvedi

13 Assertions  Placing assertions in the code increases the robustness of the code by letting the programmer catch the logic errors in the early stages of the development. Assertions are generally useful for testing the pre- and post-conditions of a function A pre-condition specifies what must be true when a function is invoked. i.e., it is a statement by the programmer that a given function should not be entered unless its pre-condition is guaranteed. If it is entered anyway, the function may behave erratically. In general, pre-conditions depend on global variables and input arguments A post-condition specifies what must be true after a function completes successfully. Ritu Chaturvedi

14 Assertions #include <stdio.h> #include <assert.h> int checkEligibility (int age, int salary) { assert (age > 21); //precondition if (salary > 5000) return 1; else return 0; } Ritu Chaturvedi

15 Assertions Assertions are for programmers – not users
Once software is completed and released to end users, the assertions are disabled so that users do not see unexpected, technical messages To disable assertions, use #define NDEBUG before #include <assert.h> OR cc –DNDEBUG …. Ritu Chaturvedi

16 Version control  As we saw in Assignment 2, version control is essential for tracking code changes, enabling groups of developers to collaborate, and backing up code.  Version control is often integrated with bug tracking software – you need to be able to link bugs to specific code revisions. Ritu Chaturvedi

17 Debuggers  Debuggers allow you to monitor other programs as they execute, or to investigate why they crash. Debuggers can: Start programs with specified arguments Halt programs on specified conditions Examine program contents Change values Step through code Ritu Chaturvedi

18 Compiling for debugging
Normally, an executable file does not contain any references to the original program source code, such as variable names or line-numbers the executable file is simply the sequence of machine code instructions produced by the compiler. This is insufficient for debugging, since there is no easy way to find the cause of an error if the program crashes. Ritu Chaturvedi

19 Compiling for debugging
GCC provides the -g debug option to store additional debugging information in object files and executables. This debugging information allows errors to be traced back from a specific machine instruction to the corresponding line in the original source file. The debug compilation option works by storing the names and source code line- numbers of functions and variables in a symbol table in the object file or executable. Ritu Chaturvedi

20 Compiling for debugging
The execution of a program compiled with -g can also be followed in a debugger like DDD. Using a debugger allows the values of variables to be examined while the program is running. Ritu Chaturvedi

21 GDB The GNU Debugger is the standard (free) debugger for many Unix systems.  Current version is 6.8   Ritu Chaturvedi

22 Using GDB  First compile the program (and all modules) with debugging flags on: luna:~/321>gcc -g debug_me.c -o debug_me  Then launch the debugger (from the same directory it was compiled in): luna:~/321>gdb debug_me //debug_me.c #include <stdio.h> /* print a given string and a number if a pre-determined format. */ void print_string(int num, char* string) { printf("String '%d' - '%s'\n", num, string); } int main(int argc, char* argv[]) int i = 0; /* check for command line arguments */ if (argc < 2) printf("Usage: %s [<string> ...]\n", argv[0]); for (i=0; i<=argc; i++) print_string(i, argv[i]); printf("Total number of strings: %d\n", i); return 0; Ritu Chaturvedi

23 Using GDB – breakpoints
Next, run the program in the debugger, supplying the command line arguments: run "hello, world" "goodbye, world" The program will run to completion unless a breakpoint has been set: break debug_me.c:9 (break on line 9) break main (break on function main) Ritu Chaturvedi

24 Using GDB – printing Now you can step through the program:
next – execute command and stop step – execute command, step into if it is a function, and stop To examine variables, use: print var  The variable must be in scope. You can also display the values of expressions, casts, and functions, e.g.: print i*2 print argv[argc]  Ritu Chaturvedi

25 Some gdb commands Ritu Chaturvedi

26 Graphical Tool - DDD DDD – stands for Data Display Debugger
DDD is a visual interface to the GDB Debugger Ritu Chaturvedi

27 Why DDD Its fast Its intuitive
I use just printf statements – why do I need a debugger ? This is like sewing clothes using a needle and thread instead of a sewing machine Ritu Chaturvedi

28 Compiling for debugging
luna:~/321>gcc -g debug_me.c luna:~/321>ddd a.out & OR luna:~/321>gcc -g debug_me.c –o debug_me luna:~/321>ddd debug_me & Ritu Chaturvedi

29 Customizing DDD Line numbers: Source  Display Line Numbers
Docking toolbars: Edit  Preferences Ritu Chaturvedi

30 Setting Breakpoints If the program has run-time errors e.g. it is stuck in an infinite loop, then we want to set a breakpoint in the while loop Right-click on the line number of the while loop Select Set Breakpoint There should now be a stop-sign at that line Ritu Chaturvedi

31 Start the Program At the top of the screen, select “Run” to start your program This can also be found in the ‘program’ menu If DDD asks for arguments to your program, just leave it blank The program will halt and prompt you for input in the bottom of the window Enter a small number: something that should finish in less than a second. It should stop again at the breakpoint. (The black arrow indicates the next line to be executed) Ritu Chaturvedi

32 Next, Hover, and Step Use Next to move through the program one line at a time After each Next you can hold your cursor over each variable to see the value This is called hovering This always displays the variable’s value at the current line of execution Note Step will move down the program, one line at a time. It will also step into function calls if there are any. Next would also move down one line at a time, but would skip function calls. Ritu Chaturvedi

33 Fixing the Bug So, what’s going wrong? Leave DDD open
Open the code in your favorite editor Fix the code Recompile the code Run the code (on the command line) If you wanted to run it again in DDD, you would need to reload the code in DDD Ritu Chaturvedi

34 Ritu Chaturvedi

35 Website (DDD Tutorial) :
Two good tutorials on DDD: Ritu Chaturvedi

36 DDD and makefile If you have a makefile with several dependent files in it and you would like to use DDD, you must compile each file in the make file with the –g option and then open the executable in DDD.

37 Some Debugging Theory You have to use breakpoints strategically
Suppose you have 10,000 lines of code with no output and a segmentation fault. Where do you put your breakpoint? The Binary Search Principle of debugging You don’t look up a word in the dictionary by starting at the first letter ‘A’ page and turning hundreds of pages until you find your word (especially if your word is zebra). Like searching the dictionary, put a breakpoint in the middle of your program and look at the values there. Is your bug before or after that point? Ritu Chaturvedi

38 Examining core files In addition to allowing programs to be run under the debugger, an important benefit of the -g option is the ability to examine the cause of a program crash from a "core dump". - When a program exits abnormally (i.e. crashes) the operating system can write out a core file (usually named ‘core’) which contains the in-memory state of the program at the time it crashed. This file is often referred to as a core dump. Ritu Chaturvedi

39 Examining core files - Combined with information from the symbol table produced by -g, the core dump can be used to find the line where the program stopped, and the values of its variables at that point. - This is useful both during the development of software and after deployment--it allows problems to be investigated when a program has crashed "in the field". Ritu Chaturvedi

40 Examining core files Sample program with an invalid memory access : null.c: int foo (int *p); int main (void) { int *p = 0; /* null pointer */ printf(“%d\n”, foo (p)); } int foo (int *p) { int y = *p; return y; The program attempts to dereference a null pointer p, which is an invalid operation - In order to be able to find the cause of the crash later, we will need to compile the program with the -g option: $ gcc -Wall -g null.c -Note that a null pointer will only cause a problem at run-time, so the option -Wall does not produce any warnings. $ ./a.out Segmentation fault (core dumped) Ritu Chaturvedi

41 Examining Core Files $ gdb a.out core Core was generated by `./a.out'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x080483ed in foo (p=0x0) at null.c:13 int y = *p; (gdb) print p $1 = (int *) 0x0 Note: This shows that p is a null pointer (0x0) of type ‘int *’, so we know that dereferencing it with the expression *p in this line has caused the crash. Ritu Chaturvedi

42 Displaying a backtrace
The debugger can also show the function calls and arguments up to the current point of execution--this is called a stack backtrace and is displayed with the command backtrace: (gdb) backtrace #0 0x080483ed in foo (p=0x0) at null.c:13 #1 0x080483d9 in main () at null.c:7 In this case, the backtrace shows that the crash occurred at line 13 after the function foo was called from main with an argument of p=0x0 at line 7 in ‘null.c’. Ritu Chaturvedi


Download ppt "Debugger Ritu Chaturvedi 60-321."

Similar presentations


Ads by Google