Skip to content

CxxDebuggingTutorial

tkren edited this page Aug 10, 2012 · 1 revision

Table of Contents

C++ Debugging Tutorial

Preliminary version.

glibc

The C library uses a couple of environment variables to turn on/off debugging of malloc/free: check http://www.scratchbox.org/documentation/general/tutorials/glibcenv.html and http://tr.opensuse.org/SDB:Debugging_with_Glibc

gdb

The GNU Debugger is a valuable tool to debug programs. Check out the guide to debugging with gdb . Enter the gdb shell with

 $ gdb myprog
GNU gdb (GDB) 7.2-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from myprog...(no debugging symbols found)...done.
(gdb) run
Starting program: myprog
[Thread debugging using libthread_db enabled]
... output of myprog ...
Program received signal SIGABRT, Aborted.
0x00007ffff5fa6ba5 in raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64      ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
        in ../nptl/sysdeps/unix/sysv/linux/raise.c
(gdb) backtrace
#0  0x00007ffff5fa6ba5 in raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x00007ffff5faa6b0 in abort () at abort.c:92
#2  0x00007ffff5fe043b in __libc_message (do_abort=<value optimized out>, fmt=<value optimized out>) at ../sysdeps/unix/sysv/linux/libc_fatal.c:189
#3  0x00007ffff5fea4b6 in malloc_printerr (action=3, str=0x7ffff60baca2 "corrupted double-linked list", ptr=<value optimized out>) at malloc.c:6283
#4  0x00007ffff5fed921 in _int_free (av=0x7ffff62f1e40, p=0x7f0510) at malloc.c:4973
#5  0x00007ffff5ff0c83 in __libc_free (mem=<value optimized out>) at malloc.c:3738
#6  0x00007ffff5fac525 in __run_exit_handlers (status=1) at exit.c:87
#7  exit (status=1) at exit.c:100
#8  0x00007ffff5f91d95 in __libc_start_main (main=<value optimized out>, argc=<value optimized out>, ubp_av=<value optimized out>, 
    init=<value optimized out>, fini=<value optimized out>, rtld_fini=<value optimized out>, stack_end=0x7fffffffe088) at libc-start.c:258
#9  0x0000000000411569 in _start ()
(gdb) quit

Inside the shell, you can set breakpoints, step through the computation, and much more. The GDB refcard gives you a quick overview of available operations.

valgrind

Valgrind helps you detect memory errors.

 $ valgrind --leak-check=full myprog
 ==30691== Memcheck, a memory error detector
 ==30691== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
 ==30691== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
 ==30691== Command: myprog
 ==30691== 
 [...] # output of myprog
 ==30691== 
 ==30691== HEAP SUMMARY:
 ==30691==     in use at exit: 0 bytes in 0 blocks
 ==30691==   total heap usage: 1,711 allocs, 1,711 frees, 140,800 bytes allocated
 ==30691== 
 ==30691== All heap blocks were freed -- no leaks are possible
 ==30691== 
 ==30691== For counts of detected and suppressed errors, rerun with: -v
 ==30691== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)

The valgrind manual is available here: http://valgrind.org/docs/manual/. Impatient people can check http://valgrind.org/docs/manual/quick-start.html.

strace, dtruss

strace is a linux tool that traces system calls. A manual is available at http://linux.die.net/man/1/strace

 $ strace myprog
[...]
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(5001), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(38548), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
close(3)                                = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 12), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb325701000
epoll_create(20000)                     = 3
eventfd2(0, 0)                          = 4
fcntl(4, F_SETFL, O_RDONLY|O_NONBLOCK)  = 0
epoll_ctl(3, EPOLL_CTL_ADD, 4, {EPOLLIN|EPOLLERR, {u32=4, u64=4}}) = 0
write(2, "Client::Client()  ", 18Client::Client()  )      = 18
write(2, "127.0.0.1:5001", 14127.0.0.1:5001)          = 14
write(2, "\n", 1
[...]

On OS X, you can use dtruss instead.

gprof

As part of the binutils, gprof is used to show profiling information of your program (check also the gprof manual). Here is how. Just compile your code with gcc option -pg. If you are using autoconf/automake, just run:

 $ ./configure CXXFLAGS="-pg"
 $ make

Alternatively, you can run

 $ make -e CXXFLAGS="-pg"

Then, execute your program as usual:

 $ myprog

myprog will then automagically generate a file called gmon.out which logs call information. You can then analyze the calls of above program run using

 $ gprof myprog
Flat profile:

Each sample counts as 0.01 seconds.
 no time accumulated

  %   cumulative   self              self     total           
 time   seconds   seconds    calls  Ts/call  Ts/call  name    
  0.00      0.00     0.00      562     0.00     0.00  boost::detail::atomic_exchange_and_add(int*, int)
  0.00      0.00     0.00      485     0.00     0.00  boost::detail::sp_counted_base::release()
  0.00      0.00     0.00      212     0.00     0.00  boost::detail::shared_count::~shared_count()
  0.00      0.00     0.00      161     0.00     0.00  boost::detail::shared_count::shared_count(boost::detail::shared_count const&)
  0.00      0.00     0.00      132     0.00     0.00  boost::detail::atomic_increment(int*)
  0.00      0.00     0.00      131     0.00     0.00  boost::detail::sp_counted_base::add_ref_copy()
  0.00      0.00     0.00       77     0.00     0.00  boost::detail::sp_counted_base::weak_release()
  0.00      0.00     0.00       77     0.00     0.00  boost::detail::sp_counted_base::destroy()
  0.00      0.00     0.00       34     0.00     0.00  boost::detail::sp_counted_base::sp_counted_base()
  0.00      0.00     0.00       34     0.00     0.00  boost::detail::sp_counted_base::~sp_counted_base()
  0.00      0.00     0.00       33     0.00     0.00  boost::detail::sp_enable_shared_from_this(...)
  0.00      0.00     0.00       27     0.00     0.00  boost::unit_test::ut_detail::bcs_char_traits_impl<char const>::eq(char, char)
  0.00      0.00     0.00       19     0.00     0.00  boost::noncopyable_::noncopyable::noncopyable()
  0.00      0.00     0.00       19     0.00     0.00  boost::detail::shared_count::shared_count()
  0.00      0.00     0.00       18     0.00     0.00  boost::mutex::mutex()
  0.00      0.00     0.00       17     0.00     0.00  boost::noncopyable_::noncopyable::~noncopyable()
  0.00      0.00     0.00       17     0.00     0.00  boost::condition_variable::condition_variable()
  0.00      0.00     0.00       15     0.00     0.00  boost::condition_variable::~condition_variable()
  0.00      0.00     0.00       15     0.00     0.00  boost::mutex::~mutex()
  0.00      0.00     0.00       15     0.00     0.00  std::exception::exception()
  0.00      0.00     0.00       14     0.00     0.00  boost::date_time::int_adapter<long>::int_adapter(long)
[...]

static code analysis

static code analysis tools include cppcheck, splint, clang

Using clang is easy. Just run

 $ ./configure CC=clang CXX=clang++
 $ make

and you will automatically compile your sourcecode with clang.

Other tools (missing description)

mutextrace, leakcheck, electric-fence, google-perftools

Clone this wiki locally