CS70, Spring 2004

Homework Assignment #5: Debugging

This assignment is due at 10 P.M. on Wednesday, February 25th, 2004. The assignment is a written one, and must be submitted as a single file, a README. Refer to the homework policies page for general homework guidelines.

This assignment has only one purpose, which is to familiarize you with interactive debuggers.

Overview

The program assign_05 is a simple file shuffler. It reads lines from a file (provided on the standard input device, cin), shuffles them into a random order, and writes them to its standard output, cout. Although it is quite simple, the program can be used to perform relatively complex tasks. For example, most of your group names were produced by running the online dictionary (/usr/dict/words) through a C version of the same program and picking promising candidates. A random line can be chosen from a file such as /etc/passwd with the command:

    ./assign_05 /etc/passwd | head -1

To the best of my knowledge, the program is free of bugs except for those deliberately introduced for the assignment. However, for instructional reasons it is much less efficient than it could be.

For this assignment, you will run the program under an interactive debugger and follow a list of steps. Most steps will require you to record the answer to a question. The final result will be submitted as a README file. Other than a file header (name, date, etc.), the README should not have "documentation" components such as the program purpose or input format. Please number your answers corresponding to the step in which the question is asked, leaving gaps if a step asks no question.

The assignment is written for use with the interactive debugger ddd on Turing. It is not possible to do the assignment with a different debugger, primarily because minor debugger variations make grading impossible. Also, it is probably not possible to do the assignment by using a Windows machine to connect to Turing, because ddd expects that you will be connecting from an X-compatible display, and to the best of my knowledge Windows machines can't do that securely.

The program for the assignment is implemented using 4 files: a Makefile, a main program (assign_05.cc), and a header file (line.hh) and implementation (line.cc) for a pair of classes that support some simple operations on text lines. There is also a sample input file (hw05-input.txt). As usual, you should check out the files using cs70checkout hw05.

The assignment is divided into several sections. You should perform the sections in order. However, each section is independent, so that you can log out and come back later, or go back to the start of a section if you think you have gotten things out of whack. If you log out and come back, you will need to repeat the steps listed under "Setup".

A Note on the gvd Debugger

Besides ddd, Turing has a similar GUI debugger, gvd. Because both are built on top of the gdb command-line debugger, they have similar interfaces. Some people prefer gvd to ddd, and after doing this assignment you will find it quite easy to switch to gvd. However, DO NOT try to use gvd in this assignment; the answers to several of the questions will differ under gvd.

Assignment Procedure

    A. Preparation

  1. Check out the program and compile it by typing "make".

    B. Setup

  2. Make sure your preferred editor is set properly by typing "echo $EDITOR". If the response is the name of some other editor, fix it by typing "setenv EDITOR vi", "setenv EDITOR pico", or whatever is appropriate to your taste. (Note: these commands assume you use tcsh as your shell. If you use bash, use "export EDITOR=vi" and so forth.) It is a good idea to put that command into your .login file so that it is executed every time you log in.
  3. Bring up the ddd debugger from the command line by typing "ddd assign_05".

    C. Basic DDD

  4. There are several ways to get the program started. The very obvious Run button won't work in this case, because the program needs arguments. Instead, explore the menus to find a way to run the program that will pop up a window asking for arguments. Specify "-d" in the window and let the program run.
  5. Question: What happens? Be sure to include a description of all output that shows up in the bottom window following the "Starting program" line. You will probably have to scroll the bottom window back a bit.
  6. It seems likely that the cause of the problem is the reference to argv[argNo][0]. Sweep out this expression with the mouse (be sure to include both sets of brackets, and no more. Use the toolbar to display it. Question: What is shown in the top sub-window? (You may have to scroll to find it.)
  7. Hmmm, that's odd. The bottom window contains an obscure clue: "Cannot access memory at address 0x". Let's try looking at argv[argNo]. Question: What is it?
  8. That's not good. An easy way to display simple variables is to rest the mouse on them. Question: What are argNo and argc?
  9. It turns out that argc is the size of argv. As you know, if a C++ array foo has 5 elements, it's illegal to refer to foo[5]. Question: Why did the program violate that rule?
  10. Click on the Edit button to bring up your favorite editor, and fix the bug. Exit your editor and click the Make button. Then click the green Run button to try it again with the same arguments. A large number should appear in the bottom window. Question: What is it? (You may wish to use cut-and-paste to make sure you copy it accurately.)
  11. If you've done everything correctly so far, the program is now waiting for you to type something. Point at the any of the three windows, and type control-D on the keyboard. This is the standard Unix method of sending an EOF to a program when it is reading from the terminal. In this case, the EOF will cause the program to exit. (If you wanted to provide some other kind of input, you could have typed it now.)
  12. Finally, clean up the data display. Click on either of the displays in the top window so that it is completely highlighted, and then click the Undisp button on the toolbar. Repeat for the other display. You should now be back to two windows.

    D. Breakpoints and Stepping

  13. Run the program with the arguments "/foo/bar /baz/zap". This should cause the program to try to open two nonexistent files by those names. Question: What output do you see in the bottom window? Be sure to scroll back to make sure you see everything after the "Starting program:" message.
  14. It seems a bit odd (or at least it should seem odd) that only the second missing file is reported. The attempt to access the files is done in a function called doShuffling. You can find it quickly by typing that name in the small window on the toolbar (the one labeled "()") and then clicking Find.
  15. Without doing anything else, click the little stop sign. This sets a breakpoint at the beginning of the function. Run the program again. Question: What happens? (Be sure to report any changes in both windows.)
  16. The Next button is a good way to work your way through the function one line at a time. Hit Next until you get to the statement "ifstream nextFile(argv[argNo]);". The constructor argument is the name of the file to open. Question: What file is it trying to open?
  17. That's odd. Hit the Up button to see the line that called us. Display argv[argNo]. Question: What is its value?
  18. Hit the Down button to get back where we were. Question: Why is the value of argv[argNo] different?
  19. The cause of the bug should be fairly obvious. Fix it, recompile, and run the program again. Question: What happens?
  20. Since you're paranoid (or should be), use the Next button a few times to get to the place where the bug happened. There seems to be a bug in DDD, so if the value of argv[argNo] isn't automatically displayed, try hitting double-clicking "(Disabled)" to make it show up. Question: What is argv[argNo]?
  21. Hit the Cont ("continue") button to continue running the program at full speed. You should see two error messages in the bottom window.
  22. At this point, it may be easiest to exit and restart ddd to get rid of your breakpoints and display commands. Alternatively, you could use Source/Breakpoints... and Data/Displays... to achieve the same effect.

    E. More on Stepping and Breakpointing

  23. Use File/Open Source... to bring up a list of the source files involved in the program. Most of them are system files that aren't of interest to us, so find line.cc and open it.
  24. Find the function named LineGetter::getLine, by scrolling or searching. Then find the place in the getLine function where a call is made to the expand function.
  25. You can set a breakpoint on a line by clicking at the beginning of that line and then on the stop sign. Set a breakpoint on the line containing the expand call.
  26. Run the program again, this time giving the arguments "-s 0 assign_05.cc".
  27. When the program stops at the breakpoint, click the Next button. Question: What happens?
  28. Rerun the program with the same arguments. This time, when the breakpoint is hit, click the Step button. Question: What happens?
  29. Use Source/Breakpoints... to disable or delete the breakpoint in getLine.

    F. More on Data Display

  30. Run the program with the arguments "-s 1 hw05-input.txt". Question: Is the output random? (You may wish to compare the output to the contents of the input file.)
  31. Set a breakpoint in the randomize function (it's in assign_05.cc) and run the program again. If necessary, use Next to get to the first statement of the for loop.
  32. Display array. Question: What is its value?
  33. Double-click on the value of array. Question: What happens?
  34. If you prefer, drag the display boxes around to rearrange them. Then select the new box and choose Show All from the pulldown Show menu on the toolbar. Question: What is the value of M_start?
  35. Select M_start and choose Display/Other... on the toolbar. If necessary, add an asterisk at the beginning of the expression in the dialog box, and add "@5" at the end before displaying. Question: What is displayed? (You may have to scroll around a bit.)
  36. Without changing what is selected, click Show. Question: What do you now see?
  37. Use the Next button to step through one iteration of the loop. Question: Do the values in the array change?
  38. Set a breakpoint at the swap line, run the program again, and hit Cont. Question: What are the values of i and j?
  39. The STL swap function interchanges two values. It should be fairly obvious what is wrong here. If not, look at the comments at the beginning of randomize. Fix the bug and compile the program again. (Incidentally, the rather odd "(*array)[i]" notation is needed because array is a pointer to an STL vector, and the [i] needs to be applied to the vector rather than the pointer. The notation wouldn't be necessary if we had passed array by reference instead.)

    G. Finishing Up

  40. Make sure you have a breakpoint at the swap line in randomize, and nowhere else. If you're starting fresh, you'll have to add it; if you're continuing from part F, you'll need to delete the first breakpoint in randomize. Run the program again (with the arguments "-s 1 hw05-input.txt"). Question: What are the values of i and j when you hit the breakpoint?
  41. Make sure you have the first 5 elements of array displayed (you may have to repeat some or all of steps 31-35). Scroll around or resize your display window so that you can see the box that has line number 2 in it. Use Next to go past the swap function. Question: What is in the box now?
  42. If you need to click Next, Step, or Cont a lot of times, you can save trouble by typing in the command (bottom) window. Try this by first clicking Cont to get back to the breakpoint, and then typing c 5 to continue 5 times (only the first letter of the command is needed for these often-used operations). Question: What happens to the first two elements of array?
  43. Delete all breakpoints and run the program one last time, with the single argument "hw05-input.txt". You will see 16 words scroll by in the window at the bottom of the screen. Question: In order, what are they? (You may use cut-and-paste, and you don't have to list them one per line).

Submission Details

The only file you need to submit for this assignment is the README. As usual, use cs70submit to submit it.

Don't forget to spell-check your file.

Future Efficiency

Assign_05.cc deliberately uses a somewhat inefficient data structure for illustrative purposes. If you ever expect to use it in the future, you should change randomize so that the vector stores pointers to lines, rather than actual lines. Don't worry if you don't know how to do that right now; by the end of the course you'll be a pointer expert.


© 2004, Geoff Kuenning

This page is maintained by Geoff Kuenning.