+ Reply to Thread
Results 1 to 3 of 3

Thread: Debugging a C++/C File with GDB Debugger

  1. #1
    Newbie awesome001 is on a distinguished road
    Join Date
    Feb 2007
    Posts
    7

    Debugging a C++/C File with GDB Debugger

    GDB Debugger

    Introduction of debugger:

    A debugger is a program which can run the program. The only difference is that it can go inside of a program and it has the ability to run step by step in the program. Debugger sometimes referred to as symbolic debugger also.

    GDB Debugger:

    GDB is a debugger which is part of the Free Software Foundation's GNU operating system. Its original author is Richard M. Stallman. GDB can be used to debug C, C++, Objective-C, Fortran, Java and Assembly programs. There's partial support for Modula-2 and Pascal. It'll run on any architecture.

    Compile source code:

    In order to debug a file, first you need to compile the program. In case of gcc compiler you need -g option to compile the source code so that the output file is ready to debug with GDB. For example, if the source file is hello-world.c, the command for compilation will be:
    gcc -g -o hello_world hello_world.c
    This command will create the output/executable file named as hello_world. You have to debug the source file with this executable file.

    Run GDB debugger:

    In order to run the GDB debugger, the command is:
    gdb hello_world
    It will display the license agreement and the you will be able to see the GDB prompt (GDB). It means that you are under GDB debugger and you are all ready to start debugging your source program.

    Listing of source file:

    The list command, abbreviated by l will show you the the source program from the gdb command prompt. By default, GDB always displays 10 lines of the source code. First time list command will print the 10 lines of the source code centered on main(). Subsequent uses of list displays the next 10 lines of the source code.

    List – works similar like list but in reverse order.

    List followed by a line number will display 10 lines centered on that line number.

    Other listing operations you'll find useful:

     starting with some line number(gdb) list 5,
     ending with some line number (gdb) list ,28
     between two numbers: (gdb) list 21,25
     by function name: (gdb) list f
     functions in the other file: (gdb) list CentralDiff
     by filename and line number: (gdb) list derivative.c:12
     filename and function name: (gdb) list derivative.c:ForwardDiff

    Listing by Memory Address:

    If you know the memory location of any function then with that memory location alos you can use list command to display 10 lines of code.
    Example: list *0x801234b

    Change the default list size:

    The below command will change the list size from default 1o to 20
    set listsize 20


    Running a program in GDB:

    The run command is responsible to run the program. Run command without any argument will run the program without command line arguments. You can specify command line arguments in the below way:
    (GDB) run one two three
    It means argument #1 is one
    argument #1 is two
    argument #1 is three

    Restarting a program in GDB:

    There are several ways to do that:
     Quit GDB and start again
     Use the kill command to stopl the program and run command to restart it again.
     Use the command run. It will ask you that the program is already running. So whether you really want to start from the beginning or not?

    Some important commands:

    We can use the command “back trace” (bt) to get the stack information of the running process. It will display the stack.

    bt will display the stack. Each entry in the stack is aasociated with an integer number. So if there is any function call from the main function then there will be two entries in the stack. One for the main function and another for the new function call. Now when we are in the function body, we can move to the main function with the below command(considering main function has the frame number 1):
    (gdb)frame 1

    Breakpoints:

    We can resume a running program in three different ways. Here are the three ways:
     Breakpoint: It stops a program whenever a particular point in the program is reached.
     Watchpoint: It stops a program whenever the value of a variable or expression changes.
     Catchpoint: It stops a program whenever a particular event occurs.

    A breakpoint stops a program at a particular point of the program. For example, it can stop the program when the execution is at the line number 10 or when the execution enters the function display() or when the execution is at the line number 20 of the source file other.c

    There are four major ways to set up the breakpoint:
    1. By Function name.
    2. By Line number.
    3. By filename and line number.
    4. By address.

    By function name:

    We can assign the breakpoint by function name in the below fashion:
    (GDB) break main.
    The "break main" command sets a breakpoint at the top of main().

    By line number:

    We can assign the breakpoint by line number in the below fashion:
    (GDB) break 10
    It will create the breakpoint at the line number 10 and program execution will resume at line number 10. But one important point to remember is that internally the program execution is at the middle of line number 9 and 10. Line number 9 has been executed but line number 10 is not yet executed. It is waiting for the execution. If you give the command “next” then only the line number 10 will be executed.

    By filename and line number:

    A third way of setting breakpoints is with a filename and line number, separated with a colon. Let's set a breakpoint at line 10 of hello_world.c:

    (gdb) break hello_world.c:10
    Breakpoint 3 at 0x80483fd: file hello_world.c, line 10.

    By address:

    A fourth way of setting breakpoints is with a memory address within the process's VM space. First try to identify the address of the main function and then assign the breakoint at main with its own memory address.

    (gdb) print main
    $1 = {int (const char *)} 0x80483f4 <main>
    (gdb) break *0x80483f4
    Breakpoint 4 at 0x80483f4: file hello_world.c, line 7.
    Breakpoint numbers:
    Every breakpoint is given a particular integer number starting from 1. We can refer a breakpoint with its integer number also. We can see all our breakpoints with the command:
    (gdb) info breakpoints
    Num Type Disp Enb Address What
    1 breakpoint keep y 0x08048464 in main at main.c:6
    breakpoint already hit 1 time
    2 breakpoint keep y 0x0804846b in main at main.c:9
    breakpoint already hit 1 time
    3 breakpoint keep y 0x08048477 in main at main.c:12
    The Num field gives the identifier. The type field gives the type of the breakpoints. The Disp field (disposition) describes what will happen to the breakpoint to the next time. Keep means nothing will happen. Allthough we can disable or delete a particular breakpoint.

    Disable / Enable a particular breakpoint:
    We can disbale a particular breakpoint in this way.
    (gdb)disbale 2
    (gdb) info breakpoints
    Num Type Disp Enb Address What
    1 breakpoint keep y 0x08048464 in main at main.c:6
    breakpoint already hit 1 time
    2 breakpoint keep n 0x0804846b in main at main.c:9
    breakpoint already hit 1 time
    3 breakpoint keep y 0x08048477 in main at main.c:12
    Now see the breakpoint 2 status is disabled.
    We can again enable the breakpoint in the below way:
    (gdb)enabale 2
    (gdb) info breakpoints
    Num Type Disp Enb Address What
    1 breakpoint keep y 0x08048464 in main at main.c:6
    breakpoint already hit 1 time
    2 breakpoint keep y 0x0804846b in main at main.c:9
    breakpoint already hit 1 time
    3 breakpoint keep y 0x08048477 in main at main.c:12

    Delete the breakpoint(s):
    If you want to remove the breakpoint by its location, use clear.
    If you want to remove the breakpoint by its identifier, use delete.
    (gdb) clear *0x80483f4
    Deleted breakpoint 4
    (gdb) clear fgets.c:10
    Deleted breakpoint 3
    (gdb) clear 9
    Deleted breakpoint 2
    (gdb) clear main
    Deleted breakpoint 1
    (gdb)
    The delete command deletes breakpoints by identifier, as opposed to clear which removes breakpoints based on their location. In fact, delete n deletes the breakpoint with identifier n.
    Resume a running program:
    Here are the details:
    1. Continue: We can resume the execution of a program by the command “continue”.
    2. Next: Execute a single line in the program but treat function calls as a single line. This command is used to skip over function calls.
    3. Step: Execute a single line in the program. If the current statement calls a function, the function is single stepped.
    Inspecting a variable:
    We can see the vale of a variable by the command “print'. For example, if we want to print the value of the variable I, then the command will be:
    (gdb)print I
    We can use the command “ptype” to see the type of the variable for example whether the variable is an interger or float or double etc. We can use ptype to look at the structure also.
    Inspecting arrays and structures:
    The below command will display the contents of an array:
    (gdb) p myIntArray
    $46 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    If you want to print 5 elements of myIntArray, starting at element 3:
    (gdb) p myIntArray[3]@5
    $49 = {3, 4, 5, 6, 7}
    You can also print structures:
    (gdb) p myStruct
    $2 = {name = 0x40014978 "Miles Davis", EyeColour = 1}
    Since it does not looks good. You can set pretty printing of structures by set print pretty:
    (gdb) set print pretty
    (gdb) p myStruct
    $4 = {
    name = 0x40014978 "Miles Davis",
    EyeColour = 1
    }
    (gdb)
    if you only want one of the elements of the structure, you can print it in the way
    (gdb) print myStruct.name
    $6 = 0x40014978 "Miles Davis"
    Changing Variables:
    We can change a variable in the below way:
    set myvar = 10;
    Finding out the current execution position:
    The command is “where”
    Debugging a running process:

    In order to do that first we need to run the process as a background job. We can do that in this way:
    $ ./print-the-number &
    It will show the process number.
    After that we can start gdb session with that process number in the below way(considering the process number is 17399):
    $ gdb print-the-number 17399
    Attaching to program: code/running_process/print-the-number, process 17399
    0x410c64fb in nanosleep () from /lib/tls/libc.so.6
    (gdb)
    There is another way to attach a process with the gdb session. The command is “attach”.
    $gdb
    (gdb) attach 17399.
    It will attach the process with this gdb session.
    Now if we want we can use detach command to detach the process from the gdb session.
    Note: One important point to remember here is that when we attach any running process with the gdb session the process pauses at that point. Again when we will detach or quit from the gdb session, the process will start executing from that position only.

    Debugging an infinite loop example:
    Consider the below program inf.c:
    //inf.c //program to debug infinite loop #include<stdio.h> #include<ctype.h> int main(int argc, char *argv[]) { char c; c = fgetc(stdin); while(c!=EOF) { if(isalnum(c)) printf("%c",c); else c = fgetc(stdin); } return 1; }
    Lets first compile the program:
    $ gcc -W -Wall -g -o inf inf.c
    Now run the progarm:
    $./inf
    Sudipta
    SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSS…………………
    So it seems from the o/p that the problem is because of infinite loop. Now let us do the debug with GDB.
    $gdb inf
    (gdb) run
    Starting program:/home/sudipta/inf
    Sudipta
    SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSSSSSSSSSSSS^C
    Program received signal SIGINT, Interrupt.
    0xb80f7430 in __kernel_vsyscall ()
    (gdb)bt
    #0 0xb80f7430 in __kernel_vsyscall ()
    #1 0xb8041393 in write () from /lib/tls/i686/cmov/libc.so.6
    #2 0xb7fdab3c in _IO_file_write () from /lib/tls/i686/cmov/libc.so.6
    #3 0xb7fdbcb7 in _IO_do_write () from /lib/tls/i686/cmov/libc.so.6
    #4 0xb7fdb765 in _IO_file_overflow () from /lib/tls/i686/cmov/libc.so.6
    #5 0xb7fde4e3 in __overflow () from /lib/tls/i686/cmov/libc.so.6
    #6 0xb7fd3507 in putchar () from /lib/tls/i686/cmov/libc.so.6
    #7 0x080484c0 in main () at inf.c:16
    Now lets go to the main function and print the value of c
    (gdb) frame 7
    #7 0x080484c0 in main () at inf.c:16
    16 printf("%c",c);
    (gdb) p c
    $1 = 83 'S'
    Now do some next and we will get the below o/p:
    (gdb) n
    Single stepping until exit from function putchar,
    which has no line number information.
    main () at inf.c:13
    13 while(c!=EOF)
    (gdb) n
    15 if(isalnum(c))
    (gdb) n
    16 printf("%c",c);
    (gdb) n
    13 while(c!=EOF)
    (gdb) n
    15 if(isalnum(c))
    (gdb) n
    16 printf("%c",c);
    (gdb) n
    13 while(c!=EOF)
    (gdb) n
    15 if(isalnum(c))
    (gdb) n
    16 printf("%c",c);
    (gdb) n
    13 while(c!=EOF)
    From this it looks like that the lines 13-16 are repeating every time. And this is the reason of this infinite loop problem. So now we identified the problem of infinite loop.

  2. #2
    Programmer Feral is on a distinguished road
    Join Date
    Jul 2008
    Posts
    160

    Re: Debugging a C++/C File with GDB Debugger

    gdb is nice for a command line solution, but personally I use ollydbg. I had also used softice in the past, but never really cared for it, tho I never really took the time to use it.

    Tho since olly is windows only I have use kdbg on linux.

  3. #3
    Code Warrior dargueta has much to be proud of dargueta has much to be proud of dargueta has much to be proud of dargueta has much to be proud of dargueta has much to be proud of dargueta has much to be proud of dargueta has much to be proud of dargueta has much to be proud of dargueta's Avatar
    Join Date
    Oct 2007
    Age
    19
    Posts
    2,848
    Blog Entries
    8

    Re: Debugging a C++/C File with GDB Debugger

    Post this in the Tutorial section. Good, though.

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Similar Threads

  1. Project: ionFiles - Joomla Simple File Download
    By Jordan in forum Community Projects
    Replies: 369
    Last Post: 01-30-2010, 01:10 PM
  2. Creating an Executable Jar File
    By TALucas in forum Java Tutorials
    Replies: 12
    Last Post: 01-14-2010, 01:03 PM
  3. Creative Debugging
    By marwex89 in forum Tutorials
    Replies: 19
    Last Post: 11-11-2008, 02:30 PM
  4. Replies: 0
    Last Post: 01-18-2008, 06:38 PM

Bookmarks

Bookmarks

     
        Algorithms and Data Structures

        Java tutorials

        Algorithms Forum

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts