28 Intermediate C Programming
This uses gcc to convert the source file of the C program (p1.c), into an executable file that
the computer can understand. Adding -g enables debugging so that we can examine the
call stack. Adding -Wall and -Wshadow enables warning messages. Shadow variables will be
explained in Section 4.1. Warning messages are sometimes benign, but they usually indicate
deeper problems in the code. It is good practice to always enable warning messages, and to
act on gcc’s advice. The name of the output file (i.e., the executable file) is specified by -o.
In this example, p1 is the output of the gcc command and, thus, is the executable file (i.e.,
the program). It can be run in the terminal by typing:
$ ./p1
The output should be the same as the following:
g1: a = 7, b = 23, c = 690
g2: a = 4, b = 34, c = 690
main: a = 5, b = 17, c = 656
To view the call stack, we will need to start the debugger. In this example, we will use
DDD (Data Display Debugger). DDD is a graphical user interface for the GDB debugger.
Start DDD, go to the menu and click
File - Open Program - select p1 - Open
Here, we have selected the executable program, not the .c file. The debugger will automat-
ically find the .c file based on information that gcc leaves in the executable. This is useful
when debugging a program that uses multiple source files.
Set breakpoints at the two functions g1 and g2 with the following commands after the
(gdb) prompt in the bottom window:
(gdb) b g1
(gdb) b g2
The command b g1 instructs DDD to set a breakpoint when the function g1 starts.
When the program reaches the first line of g1, the program will stop and you will get a
chance to check the status of the program. The command b g2 instructs DDD to similarly
set a breakpoint when the function g2 starts.
Execute the program by typing the following command at the (gdb) prompt:
(gdb) run
The program will start, and then pause at the breakpoint of function g2. Why does the
program stop at g2, not g1? Because main calls g2, so g2 is encountered before g1. If
several breakpoints are set, the program will pause at the breakpoints based on the order
in which they are executed, not the order in which they are set. In this example, although
the breakpoint at g1 is set first, the program executes g2 first. Thus, the program pauses
at the breakpoint g2 first.
To continue the program, type the following command:
(gdb) continue
The program will continue executing and then pause at the next breakpoint, located at
function g1. The call stack can be viewed by asking for the backtrace. This is done with
the following command:
(gdb) bt