Laboratory 6 - Troubleshooting C Problems


Objectives

  1. Learn to use splint, an alternative to lint, and gdb, the Gnu debugger
  2. Learn about information available in your program about errors
  3. Get some insight into ways to troubleshoot problems in your programs

Preparation

No pre-lab for this one.

In Lab Activities

In this lab, you'll get to look at some tools that can make your life as a programmer easier. The first tool is lint - this is a tool for checking your C code for problems before it explodes or produces bad results. Here's a brief tutorial on lint. It gives you a general idea of the sort of things that the lint tool can do. We don't have a version of lint itself available on the lab computers; instead, we have splint. If you enter

on the Unix command line, it will display the program options; in addition, there is online help available.

The next tool is probably more important - the gdb command line debugger. This is a pretty primitive tool, and there are a number of different wrappers around it to make it easier to use, but unfortunately, those tools don't appear to be installed on the lab machines. So you'll get a chance to see the basic tool.

Here's a quick tutorial on gdb. For a more complete reference, see the Gnu Debugging with GDB manual, or Peter Jay Salzman's Using Gnu's GDB Debugger manual. These are both very well organized, but they are too verbose for an introduction.

For the lab, first do the lint tutorial, using splint instead of lint. Generate the output, fix the errors identified by splint, and relint the code. Note that the command line parameters for splint differ from those of lint - the command line

is the equivalent of the

Answer the questions listed below about lint.

Next, go through the gdb tutorial - make sure you understand how the tool works.

NOTE: the gdb tutorial discusses loading a core file into gdb. It appears that all user accounts on esus and on the lab machines are currently set up so that when a program dies (i.e. with a segmentation fault), they do not "dump core" (generate a core file). Luckily, this is simply due to a ulimit setting that you can change. At the Unix command prompt, enter

It will likely display "0", meaning that you cannot create a core file of more than 0 blocks with any executable run by this login. To change it so you can actually generate a core file, just enter
This will allow the program to generate a core file up to 500 blocks long, which should be big enough. (The block size on the CS lab machines appears to be 1 KB.)

Remember that this ulimit will be reset to zero each time you log in, so you will need to change it any time you want an executable to be able to create a core file. (You can put the ulimit command in your .bashrc or .profile if you want it to be in effect each time you log in.)

Once you have run through the tutorials, do the following exercise.

GDB Example

Create a link to the executable gdb_example in my CS440 directory; you can do this with the command

(You're just creating a link so you don't need to copy the executable to your directory, and you don't need to type in the full path name to it every time you want to do something with it.)

Now make sure you've set your ulimit so you can generate a core file, and run the program with no arguments. It should generate a core file. Load the core into gdb and determine where and why it crashed. For the lab report, include a copy of the stack trace showing where the program died and show each of the gdb commands that you used that was helpful in pinpointing the cause of the problem. If you try a bunch of commands and they aren't helpful, you don't need to include them. But for example if you print the value of a variable and that helps you understand what went wrong, include the command and its output in the lab report.

After you've figured out why the program core dumped, quit gdb, and start it running on gdb_example again. Run the program with the command line arguments out_file123 5000000. It should core dump again; figure out why it died. Include a stack trace and the commands you used to figure out what went wrong. After you have determined the cause of the error, set a breakpoint right before the place where it crashes and restart the program with the same arguments. When it reaches the breakpoint, use gdb to change the value of an integer variable so that the program will run successfully (a value of 50 will be fine - the variable to change should be apparent to you once you figure out why it died). Continue execution of the program and verify that it successfully runs to completion. Capture the commands you used to set the breakpoint, restart the program, change the variable, and continue execution.

Note that there are other capabilities of gdb, including commands to debug multithreaded programs. One of the handiest features when you are working on your network programs is the ability to attach to a running process. If you have started up your TCP server program, you can do something like this:

Other Tools

There are a lot of other tools out there to assist you with programming - programs to help find memory problems, tools to analyze the quality of code (meter), etc. One that you might find helpful if you are working on freeware code is a source code formatter called indent. This is available on the lab machines; just do man indent to see what you can do. Beware; the program has about a billion different options, but it can be invaluable if you are stuck maintaining sloppy code.


Lab Report

Your lab report should include answers to the following questions about splint:

For the gdb example, the lab report should include the following information:

Make sure that you are following Anthony's submission guidelines.

The lab write-up is due by the end of the day Wednesday (i.e. 11:59 PM) for the Tuesday lab section and by the end of the day Friday for the Thursday lab section.