Wednesday, January 30, 2013

HOWTO Debug Crashes in C/C++ Applications on Ubuntu

In this howto we'll cover:
  • Compiling C/C++ code for debugging
  • Allowing debugging
  • Viewing errors
  • Fixing common gdb issues
Your computer is happily humming along and your program is progressing fine, suddenly disaster strikes! Segmentation fault (core dumped) your computer yells before it plunges back to darkness and your friendly shell prompt reappears.

The way of debugging in Ubuntu when coding by hand is not nearly as nice as popping up an IDE, but when done right can be much faster.

Our Problematic Code

For demonstration we'll be using this bit of code that is written to cause crashes.
int main()
{
int* p = 0x0000007b; // The cause of many a Windows XP BSOD
int j;

for(j = 0; j < 10000000; j++)
{
p++;
*p = j;
}

return 1;
}
In order to get the best debugging results you'll have to compile your code with the -ggdb flag, in this instance: gcc -ggdb killer.c.
If you run this program, it will die nearly right away with the error: Segmentation fault (core dumped).

The -ggdb flag to the compiler instructs it to include lots of debugging information. However, you won't want this on production executables because it takes up a lot of space. This example program was 9.6K with symbols, and 6.2K without!

Enabling the Dump

By default, Ubuntu 12.10 won't output crash information for programs you make yourself, to fix this you'll need to run the command:
ulimit -c unlimited
This will need to be run every time you log back on to your system.

Debugging

Once you have logging enabled and your program crashes a file called core should appear in the directory from which you ran the program. Use the gdb command to see what information it contains about the crash.
gdb a.out core
Where a.out is the name of your program that crashed and created the core file.

Analyzing the Debug Output

GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 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 /home/joseph/Desktop/a.out...done.

[New LWP 13663]

warning: Can't read pathname for load map: Input/output error.
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004004ed in main () at breakme.c:9
9 *p = j;
This is the output you'll get from the gdb command, all you want is the last three lines, from the top they tell you:
  1. What happened.
  2. Where the error happened (in main in file breakme.c on line 9)
  3. What the line was.

Common gdb Errors

  • warning: exec file is newer than core file. means the core file you're using wasn't made by your executable, you'll need to delete it and run your program again.
  • warning: core file may not match specified executable file. means the core file you're running against probably wasn't made by the program you specified, gdb will probably report wrong results.

No comments:

Post a Comment