next up previous
Next: Debugginga core Up: Using a debugger Previous: Using a debugger

Memory faults

A memory fault occurs when a program is trying to read from or write to memory that does not belong to that program. A standard example is reading/writing address 0 (ie. a NULL-pointer), this will always result in a memory fault. A debugger can catch a memory fault and is therefore a useful tool to quickly determine where in your program the memory fault occurs.

Suppose we have a very small program (bug.c) with a (obvious) bug:

/* simple buggy program to demonstrate GDB */

#include <stdio.h>


void printptr(int* iptr)
{
    printf("%d\n", *iptr);
}


int main()
{
    int a = 5;
    int* ptr = 0;

    printptr(&a);
    printptr(ptr);
}
After compiling and running, it will generate a memory fault:
 gcc -o bug bug.c
 bug
5
Memory fault - core dumped

How to find the bug with a debugger? First, make sure the executable contains debug information. This is done by providing some special flag (-g) to the compiler:
 gcc -g -o bug bug.c
Next, run the debugger with the executable as argument:
 gdb bug
GDB is free software and you are welcome to distribute copies of it
 under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (sparc-sun-solaris2.3), 
Copyright 1994 Free Software Foundation, Inc...
(gdb)
(gdb) is the prompt of the debugger; you have to type the commands you want to give at the prompt.

Now tell the debugger to run the loaded program:

(gdb) run
Starting program: /home/se/doc/debug/source/bug 
5
 
Program received signal SIGSEGV, Segmentation fault.
0x106b4 in printptr (iptr=0x0) at bug.c:8
8           printf("%d\n", *iptr);
(gdb)
The debugger stops at the offending instruction, here printf("%d\n", *iptr);. It states in which function the statement resides and with what arguments that function was called. It's immediately clear what the problem is: iptr is a null-pointer. This can be verified by telling the debugger to print the value of iptr:
(gdb) print iptr
$1 = (int *) 0x0
(gdb)

When the offending statement is in some function that's deeply nested, it can be useful to know the calling sequence from main to the that function. This is done by giving the command backtrace (abbreviated to bt):

(gdb) bt
#0  0x106b4 in printptr (iptr=0x0) at bug.c:8
#1  0x106f4 in main () at bug.c:18
(gdb)



SE Praktikum
Tue Aug 13 11:13:23 MET DST 1996