Lab 3 (10 points)
 February 2-3, 2010

Laboratory Assignment #3 —
The gdb Debugger and Using Files in C

Due: at 11:59 pm on the day after your lab session


To learn to how to use the gdb debugger for your C programs. Also, to learn how to access files in C programs.


The program gdb is a simple, command-line debugger that lets you look inside your program while it is running. For all but the simplest programs, a debugger is an essential tool that saves you many hours of development time and many frustrations about why something is not behaving the way you expect it to behave. For most modern projects, and in most professional situations, you would use a window-based debugger or an integrated development environment that has a debugger, editor, and other tools collected together in a coherent way. This lab teaches you the basic usage of a debugger in a command line environment.

Here are some useful gdb commands:

        help                    help

        list                    display the next ten lines

        list  <line number>     display ten lines centered around

                                <line number>

        list -                  display ten lines previous to the lines

                                just printed

        print <variable name>   print the value of a variable

        print <expression>      evaluate the expression and print the result

                                Note: expression can call functions in your


        break <function name>   set a breakpoint at the start of a function

        break <line number>     set a breakpoint at the specified line

        cont                    continue execution after a breakpoint

        clear <function name>   remove all breakpoints from function

        run                     run program with optional arguments

        step                    resume execution for just a single statement

        next <N>                resume execution for just a single statement
                                but treat each function call as one statement

                                If N is specified, resume execution for N


        advance <line number>   resume execution until line number is reached

        advance <function name> resume execution until function is reached

        quit                    exit the debugger

        backtrace               shows layers of functions you are into

A breakpoint is just what the name implies — a point at which you temporarily suspend the currently-executing program and give control to the debugger. You can then check out the states of variables to make sure they contain the values they should contain at that point. If you reach a breakpoint and you find something amiss, you know that there is a bug in your program in the lines that executed prior to the breakpoint. If, on the other hand, everything looks OK, you can narrow down your search for bugs in the lines that execute after the breakpoint. Loops are usually good places to put breakpoints; start by placing a breakpoint immediately before a loop and immediately after. If it looks like there may be a problem inside a loop, place a breakpoint within the loop to break during each iteration. This way, you can make sure the loop control variables and other variables contain the correct values.

There are many other commands beyond the ones listed above. You should consult the help command to list them, and you should try them out and experiment with what they do. More information about gdb can be found at

Part 1: Debugging

1.      Sign the attendance sheet.

2.      Create a directory to hold the files for Lab 3, and change to that directory now. Download file at the following URL into your directory:–

Build this program using the command:–

gcc –Wall –g –o craps craps.c

The –o craps specifies the name of the executable program. The -g switch tells the compiler to prepare the program for debugging. The compiler will add information about line numbers, variable names and locations, and other stuff to the object file so that the debugger can find its way around the program.

3.      Start the debugger by executing the command

gdb craps 

You'll see a welcoming message followed by the debugger's prompt:


It helps if you make your command shell or PuTTY window as tall as possible and still fit on the screen. It also helps (but is not essential) to have a copy of craps.c open in a second window such as a kwrite or emacs window.

4.      Type the following command:–


This will dipslay 10 lines around the next line to be executed — in this case, the beginning of the function main().

list rollDice

This will display 10 lines around the function rollDice, which starts at about line 80.

list 20, 40

This will list lines 20-40 inclusive. You can use the command help list to discover more listing options.   

5.      Run your program by typing the command


You will see that the program runs normally, just as if you had tried to run it in a command shell. (If your program were to require command-line arguments, you would supply them as arguments to the run command.) Type help run for more information.

6.      Next, you will set a breakpoint using the command

break rollDice

This will cause the program to be suspended whenever the function rollDice is called. Once suspended, you can use the debugger commands to poke around your program,.

7.      Run your program again by typing run. You will see that it stops at line 86. Now single-step through the next line by typing


This causes execution to continue for just one line, and line 87 is displayed. Note that the line displayed is the next line to execute, not the one you just finished.

Now type

print die1

to display the value of the variable die1 that was the left side of the assignment statement of line 86. It will display a random value in the range 1-6 inclusive.

You have not executed line 87 yet, so the variable die2 should not have been set to a valid value. Type print die2 to see what it is; you should see a garbage value.

8.      Type step a few more times until you have returned from the function rollDice. You will now be back in the function main at line 26. Print the variable sum, which is also the value of the switch expression of line 26. List lines 25-47 inclusive, and guess which case of the switch statement will be executed based on your value of sum.

Now type step just once to see which case it follows. Was your guess correct?

Finally, type cont to continue your program. Depending upon what happened in the switch statement you just executed, your program will exit normally, or it will iterate and call rollDice again. If it breaks at rollDice again, type cont until it eventually exits.

9.      Type run to run the program again from the beginning. Note that it will break at rollDice again. When it does, type clear to remove the breakpoint. Now step five or six times until you have returned to main(). Type break to set a new breakpoint at this line.

10.  Continue to experiment with these and other debugger commands. If you discover something new and interesting, please share it with your neighbor or classmate.

11.  Make a copy of the contents of your command shell window. This is easy if your shell is konsole – simply type CNTL-a and copy the text using the copy command in the Edit menu. If you are using PuTTY, right click in the title bar of the window to bring up the PuTTY menu; about 2/3 of the way down is a command called Copy All to Clipboard. Invoke this command. Now paste the contents of what you copied to a new file called screen.txt. This is the file you will turn in for this part of the lab.

Part 2: Accessing Files in C

Write a simple file copy program called copy. This program takes two arguments on the command line, namely the file to be copied from and the file to be copied to. Your program needs to do four things:–

·        Interpret the arguments on the command line to get the file names.

·        Open the two files

·        Copy the contents of one file to the other

·        Close the two files

File operations are described in §7.5 of Kernighan and Ritchie and in Chapter 11 of Deitel and Deitel.. To open a file, use the following function (declared in <stdio.h>):–

FILE *fopen(char *name, char *mode);

This function “opens” the file whose name is given by the null-terminated string name. The mode can be one of "r" for read access, "w" for write access, and "a" for append access. (There are other possible modes, but these will suffice for now.) This function returns a pointer to an object of type FILE, which type is a typedef of an opaque data structure maintained by the operating system. When a file is opened with mode "w", it is created if it does not exist. If it does exist, all of its contents are overwritten. If the file could not be opened for any reason, fopen returns the NULL pointer.

The opposite of fopen() is

int fclose(FILE *fp);

This flushes any output buffers of the file pointed to by fp, and then it “closes” that file, thereby making it no longer available for reading and/or writing.

To read and write files character-by-character, use the following functions:–

int getc(FILE *fp);
int putc(int c, FILE *fp);

The following function, adapted from page 17 of Kernighan and Ritchie, will copy the contents of one file to the other:–

copy(FILE *in, FILE *out) {
   int c;
   while ((c = getc(in)) != EOF)
        putc(c, out);

Example files that you can use to test the program can be found at

You can compare your output file to the input file using the diff command in the Linux shell. To get credit for this part of the lab, capture the screen of your command shell showing the execution of your copy command followed by the diff command.

Submitting this Lab

To get credit for this lab, submit your files as follows:–

/cs/bin/turnin submit cs2303 LAB3 <your screen captures>