CS115 Lab: Introduction to make and gdb

Highlights of this lab:

The purpose of this lab is to introduce you to tools that make compiling and debugging easier.

Lab Exercise:

Click the little computer above for a detailed description.
NOTE: You do NOT have to hand in this lab exercise, but doing it will help you in your class.

"New" Unix/Linux Commands

Here are some more Unix/Linux commands that you need to learn. Remember that you can enter man command to get a complete description of any Unix/Linux command and its options.

Command Description
cal [month #] year Prints a calendar of the specified year. e.g. cal 2010
If a month number is specified, prints only that month. e.g. cal 3 2010 (for March 2010)
cat file1 [file2 ...] Concatenate (join together) specified files and direct the output to the standard output device - the screen.
This command is commonly used to display the contents of one file on the screen. (It's simpler than getting in and out of an editor.)
date Print the current time and date.
who Lists who is logged into a machine. It provides information such as the user's login name and the time when the user logged on.
w Lists who is logged into a machine. Provides information such as the user's login name and the time when the user logged on. It also provides information about what the user is curently doing.
sort Sorts the input stream or the contents of files. To sort the contents of a file, use sort filename.
wc Displays the number of lines, words and characters in a file. To display only the number of lines, you can use wc -l.
file file Perform tests on a file to determine its type. Useful if you want to make sure a file is not an executable before you try to edit it.
cmp file1 file2 Compare two files to see if they are the same. Reports just the first difference unless you specify -l
diff file1 file2 Displays the differences between file1 and file2. This lists the changes necessary to convert file1 to file2.
find path option Search down directories for a file. e.g. find   ./   -name gold.cpp would search in the current directory and in all subdirectories for the file called gold.cpp
grep [option] string [file(s)] Search for a string pattern in a file. There are several options. e.g. grep   namespace *.cpp would search the current directory for the string "namespace" in all .cpp files and show the lines in each file where the string occurs. e.g. grep   -n   namespace *.cpp would perform the same search but also give the line numbers in which the string was found.
ps Lists the processes that are running for a terminal. To see all the processes that are running for you, use ps -fu yourusername. This command is often used with kill.
kill [option] processid Kill the process specified. e.g. kill -9 1455 would perform a "sure kill" (option 9) on process id "1455". This is a handy command if you change your mind after sending a job to the printer and want to delete it from the queue. See the lpq command to see how you can query the print queue for process ids.
lpq -P[printername] Query the specified printer to see active jobs. Reports process ids of jobs. e.g. lpq -Pcl122
quota -v Show how much disk space you are using ("usage") on a multi-user Unix system and what your limit is ("quota"). The numbers given refer to kilobytes of space.


Separate Compilation

If you only have one file to compile (for instance, hello.cpp), you can use:

g++ -o hello hello.cpp
However, in this lab, you will be more often working with multiple files

Let's work with an example. You can get three files by entering the commands:

cp /net/data/ftp/pub/class/170/ftp/cpp/SeparateCompile/main.cpp main.cpp
cp /net/data/ftp/pub/class/170/ftp/cpp/SeparateCompile/myFunction.cpp myFunction.cpp
cp /net/data/ftp/pub/class/170/ftp/cpp/SeparateCompile/myFunction.h myFunction.h
Note that both main.cpp and myFunction.cpp each have a reference to the .h file myFunction.h. You will have to compile each of these files separately to produce .o files and then link them all together. The following commands show how to do this. Notice the -c option you need to specify when you want to compile only, not to compile and link.

Compile only: g++ -c main.cpp
Compile only: g++ -c myFunction.cpp
Link: g++  main.o   myFunction.o  -o main
If you wanted to compile a whole set of C++ programs at the same time, you could enter: g++ -c *.cpp Be careful with this though, for these reasons:

To link a whole set of object files you could have just entered: g++   *.o   -o main Again, you should be careful that you have all your files in one directory.

The following diagram illustrates how the previous example appears conceptually:

Building Executables with "make"

You can use the Unix utility called make to help you create an executable file from several C++ files. There are many other uses for make, but this lab focuses on how to use it to help simplify working with C++ files. Here is a list of references for using make: When you type make at the Unix/Linux command prompt, it looks for a file called Makefile or makefile which you would have created with a text editor. Inside the Makefile you have to put in the names of the C++ and object files that you need to create the executable file for the C++ project you are working with.

Let's look at an example of how you would create a C++ project without a Makefile. We can then see how to make life simpler by using a Makefile to create that same C++ project.

We will work with files that you may have seen before. If you don't have them, you can copy them now:

cp /net/data/ftp/pub/class/170/ftp/cpp/SeparateCompile/main.cpp main.cpp
cp /net/data/ftp/pub/class/170/ftp/cpp/SeparateCompile/myFunction.cpp myFunction.cpp
cp /net/data/ftp/pub/class/170/ftp/cpp/SeparateCompile/myFunction.h myFunction.h
To obtain an executable, you must type: Now every time you make a change to either main or myFunction, you have to recompile the file that you modified and then perform the link again. And if you make a change to the .h file that all of those .cpp files depended upon, you have to recompile everything and do the link again. Of course you can just do this: but that is time-consuming and not at all necessary. It is much better to only compile the files you need to. This is where a Makefile can help you.

You have to be observe a little syntax when you create your Makefile with a text editor. Here are a few very simple rules:

This is a simple introduction to Makefiles. As you become comfortable with them you will find that you can elaborate with targets to clean up old .o files and so on. However, to start, here is a simple Makefile to deal with the myFunction project.
# Makefile to create the basic myFunction project

main.o:  main.cpp myFunction.h
        g++ -c main.cpp

myFunction.o: myFunction.cpp myFunction.h 
        g++ -c myFunction.cpp

main: myFunction.o main.o
        g++ myFunction.o main.o -o main
Now that you understand what is in a Makefile you need to know how to use it. It's quite straightforward - simply enter make target at the system prompt. The make process will report on what it is doing. The following examples illustrate how to compile a single module, and how to link all files.
[26]% make myFunction.o
        g++ -c myFunction.cpp

[27]% make main
        g++ -c main.cpp
        g++ myFunction.o main.o -o main
If you enter a target that is already current, "make" reports that.
[22]% make main.o
main.o is up to date.
The bottom line here is that Makefiles help you work with multiple C++ files that make up a project. By only compiling the C++ files that you have to compile, you save a lot of time recompiling files needlessly. For greater detail on Makefiles, go back to any of the tutorials given at the start of this explanation.

Debugging C++ with gdb

There are two kinds of errors that you will encounter as you develop projects in C++. The problem of how to resolve the logic error remains. You could guess where in your program the error occurred and put in some cout statements there to print out the value of variables to see what was happening. Sometimes this works but then you're left with having to delete all the cout statements and hope that you don't accidentally take out some good code while you're doing it.

A better solution is to use a debugger program so that you can control how your program is running. Here are some of the basic actions you want to perform:

Running the gdb Debugger

Before you can use gdb on a program, you must prepare your program for debugging with gdb. You must compile it with the -g or -ggdb option. The -g option creates additional information about the program and deposits it in a symbol table. (The -ggdb option creates more information of this type.) The debugger must have this symbol table to do its work. The general syntax is:
        g++ -g filename.cpp -o executable_file
Start gdb by typing in the following command:
        gdb executable_file
where executable_file is the executable version of the program. Remember: if you do not use the -o option when you compile a program, the executable file will be called a.out.

The system prompt changes to the gdb prompt, and you are ready to start entering gdb commands. There are many commands available but the following table shows some of the basic ones.

GDB Command Summary

Command Action
help Display information about gdb commands.
run Start running the program under gdb.
print expression Display the contents of a variable or expression.
break function Set a breakpoint at the designated function.
clear function Clear the breakpoint set at the designated function.
delete [number] Delete all breakpoints if no number is specified, or deletes just the breakpoint specified by number.
info breakpoints Display the number of each breakpoint.
step Execute just the next line of code.
next Execute just the next line of code but skip over any function calls in the line.
list Display lines of source code.
quit Exit gdb.

As is the case with most debuggers, the best way to learn gdb is to actually use it on a program. There is an simple program you can use to do this in the lab exercise. Here is a list of the references for using gdb:

On Hercules Use dbx

If you would like to learn the debugger on Hercules, please click here

Lab Exercise:

This page last modified:
Friday, 04-Jan-2008 12:27:15 CST

CS Dept Home Page
CS Dept Class Files
CS115 Lab Files

Copyright: Department of Computer Science, University of Regina.