Debugging Guidelines

Before You Stop by Office Hours

  1. Incremental Code Development - You should be developing your code using incremental code development. That means that you add a little bit of code and verify it works before moving forward. If you stop by during office hours looking for assistance with your code, the first thing we will ask you is up to what point your code was working. If you cannot answer that question, we will not be able to help you.
  2. Tools - Run splint (e.g., splint my_code.c) and valgrind (e.g., valgrind a.out) on your code.
  3. Segmentation Fault? - If your code is generating a segmentation fault run valgrind. You can also run the debugger (gdb) and use where to identify where the fault is taking place.
  4. Simplify Input - Simplify the input that is causing the code to fail. This will help you find the problem and if you need to see us, help us locate the problem with your code.

Approach to Write Code

If you are careful and follow some guidelines, the amount of debugging you need to do is minimized. The guidelines are:

  1. Incremental code development - Write a little bit of code and verify it works before moving forward. How much is a little bit depends on your coding experience.
  2. Good variable names and indentation from the beginning - Do not wait until submission time to fix indentation and variable names.
  3. Keep backups - You can use the submit server as a backup mechanism or git (see git tutorial).
  4. Do not make assumptions - If you are not sure how a language construct works, look up information about it or write a small program that allows you to understand it.
  5. Use Tools Often - Check your code with splint, valgrind, and the additional gcc flags mentioned below often. Do not wait until you have a lot of code to use the tools. Do not wait to have a bug in order to use them.

Debugging Strategy


           1. if (segmentation fault) {
                 a. Use valgrind to locate the error.
                 b. Use gdb and the where command.
              } else {
                 if (no results) {
                    a. Program may have an infinite loop (check your loops).
                    b. Program is waiting for input.
                    c. Output statements failed.
                 } else {
                    /* incorrect results or different in the submit server */
                    a. Use the diff command to identify the differences.
                    b. If using diff does not help, simplify the input as much
                       as possible to see if you can identify the problem.
                    c. Step through the code using the debugger.
                    d. If all the above fails, use printf statements to see 
                       values, and the execution path leading to the problem.
                 }
              }

           2. Compile your code with gcc flags -fmudflapth -lmudflap as 
              they can provide additional information. 

              gcc flags -fmudflapth -lmudflap my_code.c

              You may want to have an alias set that includes these flags.
              Do not run valgrind with code compiled with these flags.
          
           3. Try splint on your code.
       

Using valgrind

The valgrind utility can be use to detect dynamic memory problems and to detect invalid memory accesses. To use valgrind make sure you compile your code with the -g option.

To run valgrind:

valgrind a.out

If you are using input redirection:

valgrind a.out < public01.in

Other options:

valgrind --leak-check=full a.out /* for details of leaked memory */

valgrind --track-origins=yes a.out /* to track use of uninitialized values */

Additional information about valgrind can be found at http://pages.cs.wisc.edu/~bart/537/valgrind.html and http://valgrind.org/

Typical Problems

  1. You get the correct results in grace, but not in the submit server - This may happen because:

Web Accessibility