- publishing free software manuals
An Introduction to GCC - for the GNU compilers gcc and g++
by Brian J. Gough, foreword by Richard M. Stallman
Paperback (6"x9"), 144 pages
ISBN 0954161793
RRP £12.95 ($19.95)

"A wonderfully thorough guide... well-written, seriously usable information" --- Linux User and Developer Magazine (Issue 40, June 2004) Get a printed copy>>>

5.1 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.(14) 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".

Here is a simple program containing an invalid memory access bug, which we will use to produce a core file:

int foo (int *p);

main (void)
  int *p = 0;   /* null pointer */
  return foo (p);

foo (int *p)
  int y = *p;
  return y;

The program attempts to dereference a null pointer p, which is an invalid operation. On most systems, this will cause a crash. (15)

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.

Running the executable file on an x86 GNU/Linux system will cause the operating system to terminate the program abnormally:

$ ./a.out 
Segmentation fault (core dumped)

Whenever the error message ‘core dumped’ is displayed, the operating system should produce a file called ‘core’ in the current directory.(16) This core file contains a complete copy of the pages of memory used by the program at the time it was terminated. Incidentally, the term segmentation fault refers to the fact that the program tried to access a restricted memory "segment" outside the area of memory which had been allocated to it.

Some systems are configured not to write core files by default, since the files can be large and rapidly fill up the available disk space on a system. In the GNU Bash shell the command ulimit -c controls the maximum size of core files. If the size limit is zero, no core files are produced. The current size limit can be shown by typing the following command:

$ ulimit -c

If the result is zero, as shown above, then it can be increased with the following command to allow core files of any size to be written:(17)

$ ulimit -c unlimited

Note that this setting only applies to the current shell. To set the limit for future sessions the command should be placed in an appropriate login file, such as ‘.bash_profile’ for the GNU Bash shell.

Core files can be loaded into the GNU Debugger gdb with the following command:


Note that both the original executable file and the core file are required for debugging--it is not possible to debug a core file without the corresponding executable. In this example, we can load the executable and core file with the command:

$ gdb a.out core

The debugger immediately begins printing diagnostic information, and shows a listing of the line where the program crashed (line 13):

$ 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
13        int y = *p;

The final line (gdb) is the GNU Debugger prompt--it indicates that further commands can be entered at this point.

To investigate the cause of the crash, we display the value of the pointer p using the debugger print command:

(gdb) print p
$1 = (int *) 0x0

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.

ISBN 0954161793An Introduction to GCC - for the GNU compilers gcc and g++See the print edition