Debug C++ codes with gdb

#notes #Linux #C++ #GDB

As there are many tutorials can be found online, like this one and this example-based one, here I’m not going to list all usages or options of gdb, but just some techniques used during my debugs.

Program with command line arguments

For a code need supply command line arguments, the gdb debug command is

    gdb --args executable arg1 arg2 ... argn

For example, an executable code named foo takes a file input as argument (contains all parameters needed by foo),

    gdb --args foo input

Debugging a crashed program

When your program is crashed, a segmentation fault, for example. Using the core dump will be very helpful in locating the causes. The basic steps are,

  • type ulimit -c unlimited in an xterm (this allows the creation of core/postmorterm files)
  • launch your program (and let it crash): a core file should now be present in the directory
  • launch the debugger with gdb yourprogram corefile or gdb –args yourprogram arg1 arg2 arg3 to run gdb with parameters
  • type bt at gdb prompt to see on what line it did crash
  • type frame framenumber to select a particular frame, and get more info
  • use list to show the code around this frame, and info locals to see the local variables and print variable to show its value

Here is an example,

    (bash) ulimit -c unlimited
    (bash) Soft2D input
    (bash) gdb Soft2d core
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    Core was generated by `Soft2D input'.
    Program terminated with signal SIGSEGV, Segmentation fault.
    #0  __GI___libc_free (mem=0x3fd00e6251f20673) at malloc.c:2951
    2951	malloc.c: No such file or directory.
    [Current thread is 1 (Thread 0x7f09e39357c0 (LWP 1057))]
    (gdb) bt
    #0  __GI___libc_free (mem=0x3fd00e6251f20673) at malloc.c:2951
    #1  0x0000000000408f87 in myarray<double>::~myarray (this=0x7ffe173923f0, __in_chrg=<optimized out>) at src/../include/myarray.h:240
    #2  0x00000000004081a1 in geometry::computeCurvesGeoProperties (this=0x651888 <run_input+136>) at src/geometry.cpp:179
    #3  0x0000000000403ea6 in input::setup (this=0x651800 <run_input>, fileNameC=0x7ffe17394f84 "input") at src/input.cpp:107
    #4  0x0000000000402be2 in main (argc=2, argv=0x7ffe17392d08) at src/main.cpp:45
    (gdb) fram 1
    #1  0x0000000000408f87 in myarray<double>::~myarray (this=0x7ffe173923f0, __in_chrg=<optimized out>) at src/../include/myarray.h:240
    240	  delete[] cpu_data;
    (gdb) list
    235	// destructor
    236
    237	template <typename T>
    238	myarray<T>::~myarray()
    239	{
    240	  delete[] cpu_data;
    241	  // do we need to deallocate gpu memory here as well?
    242	}
    243
    244	// #### methods ####
    (gdb) print cpu_data
    $1 = (double *) 0x3fd00e6251f20673

Setting breakpoints

Breakpoints are set with the break command (abbreviated b). Here are several ways to say where the breakpoint should go.

    # Set a breakpoint at entry to function function.
    break function
    # Set a breakpoint some number of lines forward or back from the position at which execution stopped in the currently selected stack frame
    break +offset
    break -offset
    # Set a breakpoint at line linenum in the current source file.
    break linenum
    # Set a breakpoint at line linenum in source file filename.
    break filename:linenum
    # Set a breakpoint at entry to function function found in file filename. 
    break filename:function
    # Set a breakpoint at address address. You can use this to set breakpoints in parts of your program which do not have debugging information or source files.
    break *address
    # Print a table of all breakpoints, watchpoints, and catchpoints set and not deleted
    info breakpoints [n]
    info break [n]
    info watchpoints [n]

Another way to start

  1. Compile your application with -g, then you’ll have debug symbols in the binary file.
  2. Use gdb to open the gdb console.
  3. Use file and pass it your application’s binary file in the console.
  4. Use run and pass in any arguments your application needs to start.
  5. Do something to cause a Segmentation Fault.
  6. Type bt in the gdb console to get a stack trace of the Segmentation Fault.