[Robot]
  Karel the Robot  

Debugging Aids




Debugging is the process of finding and reducing the number of bugs, or defects, in a computer program. Straightforward scrutiny of the program, and playing out the way it executes in your head, reveals a surprising number of the bugs. However sometimes you need extra help. For example, the program executes so quickly, you find it hard to follow. Or perhaps you aren't sure if a function you have written is even being invoked and executed. The following debugging tools may help in those cases.

"Commenting Out" code

"Commenting Out" code is one of the simplest, yet effective, ways of pinpointing bugs/defects in a program. Recall that there are two ways of making comments in C++:
  1. C++ style: using two consecutive slashes, //, to start a comment that extends to the end of that line of the program.
  2. C-style: anything enclosed between the delimiter pair /* and */. The commented section can extend over multiple lines making it particularly useful in debugging. However, bear in mind that C-style comments cannot be nested.
To illustrate using comments to find where a program defect resides in a program, consider the following program fragment that, when executed, is known to cause an execution problem:
    JumpUp();
    MoveAcross();
    JumpDown();
To find out why Karel is going on some crazy path, we can turn the last two function calls into comments, like this:
    JumpUp();
    /*
    MoveAcross();
    JumpDown();
    */
Because the compiler ignores comments (that is, does not try to translate a comment into machine language), the MoveAcross and JumpDown functions will not be invoked. Admittedly, we could have simply deleted the calls but then we would have had to remember what we had written when it comes time to reinsert the code. If Karel "jumps up" as intended, we can move the /* down, like this:
    JumpUp();
    MoveAcross();
    /*
    JumpDown();
    */
and see what happens. If we now discover that Karel does not behave as intended, we have narrowed down the bug to inside the MoveAcross function. Once we have repaired the MoveAcross function, we can remove all of the comment delimiters.

(NOTE: Once finished debugging, be sure to check that no code remains commented out. It is considered a bad practice to submit any program that still contains commented out code; see the article Code in Comments for a discussion on why this is a bad practice.)


Execution modes: Continuous versus Single Step

By default, Karel executes in Continuous mode. Toggling between Continuous and Single Step mode can be done using the statements In Single Step mode, hit the spacebar to execute the next Karel primitive procedure.

NOTE: Besides these statements (functions), toggling between the modes can be done by hitting the # key.


Trace(message);

As a Karel program runs, whenever one of the six builtin Karel primitive procedures (say, Move or TurnLeft) is executed, its name flashes in the upper left hand corner of the execution screen. The Trace function allows you to insert a message of your choosing to flash display in that same space. When program execution reaches the Trace, the single string argument to the Trace function is used as a message to be displayed.

For example, assume a programmer had placed

    Trace("End of while loop");
at some strategic spot in their program code. Then when that spot was reached and the Trace function invoked, a message would flash in the upper left-hand corner something like this:
 End of while loop                                                            .
 CORNER  FACING  BEEP-BAG  BEEP-CORNER  [A Stair Cleaning Task                ]
 (2, 3)  EAST        2         0                                              .
ST.+-----------------------------------------------------------------------+
 9 | .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . |
   |                                                                       |
 8 | .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . |
   |                                                                       |
 7 | .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . |
   |                                                                       |
 6 | .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . |
   |                                                                       |
 5 | .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   . |
   |                                                                       |
 4 | .   .   .   .   1   .   .   .   .   .   .   .   .   .   .   .   .   . |
   |               +---+                                                   |
 3 | .   .   .   1 | . | .   .   .   .   .   .   .   .   .   .   .   .   . |
   |           +---+   |                                                   |
 2 | .   >   > | .   . | .   .   .   .   .   .   .   .   .   .   .   .   . |
   |       +---+       |                                                   |
 1 | .   ^ | .   .   . | .   .   .   .   .   .   .   .   .   .   .   .   . |
   +-------+-----------+---------------------------------------------------+
     1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18 AVE.


BreakPoint(message);

The BreakPoint function combines the functionality of the Trace function and the SingleStep function into one. Whenever program execution reaches a BreakPoint function call, the string argument to the BreakPoint function is displayed in the upper left-hand corner of the execution screen and the execution mode goes to Single Step. The message will continue to appear until the spacebar is pressed causing Karel to execute the next Karel builtin primitive procedure. Further execution comes from continuing to hit the spacebar or toggling to Continuous execution mode by hitting the # key.

NOTE: The BreakPoint function is likely to be of more use than any of the other debugging functions.


Bell(rings);

Whenever program execution encounters a Bell function call, it emits a bell-like sound. Originally the single numeric argument was used to determine how many bell sounds to play, but execution of Karel has speeded up so much that the sounds run together. Also, most lab machines have no speakers, making the utility of this function rather low. It is rarely used anymore.

TIP: If using the Bell function, always invoke it as Bell(1);




Example Explanation
void FaceWestIfFacingSouth()
{
    Trace("inside FaceWestIfFacingSouth function");
    if (facingSouth)
    {
        do
        {
            TurnLeft();
        } while (notFacingWest);
    }
}
To help determine if the FaceWestIfFacingSouth() function is being invoked, the programmer has placed a Trace() at the beginning of the function. Each time the FaceWestIfFacingSouth() function is entered, the trace message will flash across the top of the Karel execution screen.
void PickBeepersToWall()
{
    if (nextToABeeper)
        do
        {
            PickBeeper();
        } while (nextToABeeper);
    while (frontIsClear)
    {
        BreakPoint("Another iteration with frontIsClear");
        Move();
        if (nextToABeeper)
            do
            {
                PickBeeper();
            } while (nextToABeeper);
    }
    Bell(1);
}
The logic to the left has Karel pick up all beepers between him and the wall ahead of him, including beepers on Karel's beginning street corner. Each time the while loop begins, a message is displayed in the upper left-hand corner of the execution screen ("Another iteration with frontIsClear") and execution pauses until the spacebar is hit or Continuous mode execution is resumed. When the while loop is finally exited, a bell sound is rung.



  When All Else Fails . . .  

Leave the problem alone and get some rest.

Often even a short break will allow your mental processes to get back on track to finding the source of your problem!

Some final advice: Often programming errors are hard to find but, once discovered, painfully obvious. Do not be too upset with yourself when you find these errors. If you find a "stupid" error, do not think "I'm really dumb"; instead think "I must be a genius to locate such an obscure and hard-to-spot error!" Granted, both are overstatements, but the second is closer to the truth than the first.

Tired Programmer



Prior Topic       |       Next Topic  

[MTSU]  | CS  | [Home] Return to Karel home page
(Credits and Copyrights)