Debugging Java Programs with CodeWarrior for CS100 and CS211}} \author{Hal Perkins} \date{\term}
\noindent CodeWarrior includes an interactive debugger that you can use to examine your program as it executes. This handout gives an overview of the debugger and how to use it effectively.
Some of the information in this handout may not make much sense until later in the course. Skim over unfamiliar material now and read it again later at the appropriate time.
\note{The CodeWarrior Pro 3 debugger has been changed. It is now part of the IDE, and not a separate application. And, some of the keyboard shortcuts for debugger commands are different.}
\section{Perspective}
An interactive debugger allows you to run your program a few statements at a time and observe the values of variables. A good interactive debugger is an invaluable tool for finding problems and verifying that a program works.
But a debugger is no substitute for thinking. The best way to eliminate errors (bugs) is not to create them in the first place. Time spent carefully designing a program is more than repaid in time saved during testing and debugging. Before you start writing detailed code, be sure you understand the problem and the algorithms you plan to use to solve it. After you've written the code, carefully check it (proofreading, tracing, etc.) before you try running it.
Don't rush to get something on the computer. You may be tempted to type in the first thing that comes to mind and start tinkering with it, because it sometimes feels like no progress has been made until the machine is involved. But if you hack before you know what you are doing, it will take much longer to get a correct program and the code will be much worse.
Rather than tinkering with your code, randomly changing things in the hope that bugs will go away, get away from the computer and think.
Take advantage of all error-detecting features provided by CodeWarrior. Turn on any options that you can find to generate warning messages. Use any available software tools to look for potential bugs. Don't waste your time on problems the computer could have caught for you.
Once you have carefully designed and typed your program, your task is to verify that it works as expected. The debugger can be a great help with this, allowing you to stop execution at ``interesting'' places and check that variables have their expected values, that expected output has been produced, and that nothing unexpected has happened.
\section{Using the Debugger}
Select \cn{\mn{Project}}{\mn{Enable Debugger}}. (On a Mac, this changes command \mn{Run} in menu \mn{Project} to \mn{Debug}.) Then select \cn{\mn{Project}}{\mn{Debug}} to have the debugger execute your program.
The debugger's {\it program\/} and {\it new class browser\/} windows usually open automatically when the debugger starts. If they don't appear, you can select them from menu \mn{Window}. In the screen snapshot on the last page of this handout, the browser window is in the upper right corner with the program right below it.
The program window contains two panes on top and one on the bottom. It displays information about currently active methods and the source files that contain them. The upper-left panel contains a list of active methods. The bottom panel displays the source file containing the method whose name is selected in the list and the upper-right panel displays its local variables. An arrow appears to the left of the next statement to be executed in each active method. Initially, execution is paused at the first statement of method \cd{main}.
The browser window looks much like the program window, but it contains three panes at the top. It can be used to view any file in the program, not just those containing currently active methods. The upper-left pane contains a list of files in the program. When a file name is selected, the middle pane contains a list of the methods in that file. Select a method name to view its source code in the bottom pane.
Arrange the debugger's windows on the screen so they don't overlap other windows, like the input/output console window, that you want to see while debugging. You can change the size of the debugger's windows by dragging the lower right corner, as usual. To adjust the size of individual panes in the windows, use the mouse to drag the vertical or horizontal bars between them.
When the debugger begins executing your program, it usually pauses at the first statement. You can cause execution to proceed by selecting \cn{\mn{Project}}{\mn{Run}}. Select \mn{Run} twice if the first selection only brings the program window forward without actually executing the program. Alternatively, you can execute the program one statement at a time, as discussed in Section \ref{secstop}.
\subsection{Breakpoints}
Before you run your program, you can set \df{breakpoints}: places in the code where you want execution to pause so you can examine the situation before continuing. Breakpoints can be set in both the program and browser windows. In the source panes of these windows, there are dashes to the left of most statements, indicating places where breakpoints can be set. (This is a good reason to put individual statements on separate lines. Breakpoints can be placed only at the beginning of a line, not in the middle.)
To set a breakpoint, click one of the dashes. It will turn into a small red dot. When the execution reaches an active breakpoint, the program pauses and control returns to the debugger.
The \df{breakpoints window} contains a list of all the breakpoints in the program. If it is not on the screen, you can select it from menu \mn{Window}.
You can temporarily disable a breakpoint without removing it entirely by clicking the red dot next to it in the breakpoints window. The dot changes to a dash. The breakpoint still exists in the program, but execution won't pause there. This is useful, for example, if you want to stop at a breakpoint the first time it is reached but not after. To reactivate a breakpoint, click the dash in the left column of the breakpoint window to cause the red dot to reappear.
A breakpoint may have a \df{condition} attached to it ---a logical expression (e.g. \cd{sum >= 17}). When execution reaches a breakpoint with a condition, it pauses only if the breakpoint is active and the condition is true. Conditions are entered in the breakpoints window to the right of the affected breakpoint.
You can view the location of a breakpoint in the source program by double clicking it in the breakpoints window. The browser window will jump to that location.
To permanently remove a breakpoint from the program, click the red dot next to the statement in the program window or symbol window (not the breakpoints window). The dot will change back to a dash to indicate that the breakpoint is gone.
\subsection{Stopping Execution of a Program}
\noindent \textbf{Macintosh.} To stop a program you are debugging (perhaps because it is in an infinite loop), type \key{control-command-/}. This should return control to the debugger. The program window will show the location in the program where execution is paused, and you can use the debugger to appraise the situation.
If \key{control-command-/} doesn't work, try forcing termination by pressing \key{Option-Command-Esc}. If you want to continue debugging, you will have to start from the beginning.
Occasionally a problem will cause the machine to lock up or freeze. If neither of the above steps salvages the situation, restart the machine. Don't do this unless you have to ---all unsaved work in open applications will be lost.\medskip
\noindent \textbf{Windows.} Usually, you can stop execution of a program by selecting a debugger window and then selecting \cn{\mn{Debug}}{\mn{Stop}} or \cn{\mn{Debug}}{\mn{Kill}}.
\subsection{Incremental Execution}\label{secstop}
Once a program is stopped, you may want to look around and run it slowly, a few statements at a time. The commands in menu \mn{Debug} do this.
The \df{step} commands run the program one statement at a time. \mn{Step Over} and \mn{Step Into} both execute the next statement in the program. If the statement calls a method, \mn{Step Over} executes the entire method call in a single step. \mn{Step Into} moves into the body of the method so you can trace its execution. Use \mn{Step Into} to examine your own methods and \mn{Step Over} for methods supplied by us or CodeWarrior.
\mn{Step Out} completes execution of the current method and stops at the place where the method was called.
\mn{Project|Resume} resumes execution until another breakpoint is reached or the program terminates.
\mn{Stop} terminates execution and returns control to the debugger. Execution can be resumed after executing any desired debugger commands.
\mn{Kill} terminates execution of the program.
\begin{note} The debugger's toolbar has buttons for \mn{Run}, \mn{Stop}, \mn{Kill}, \mn{Step Over}, \mn{Step Into}, and \mn{Step Out}. In the Windows version, this toolbar is near the top left of the program window. \end{note}
\subsection{Examining a Program}
When the program is stopped, you can examine the values of variables, check whether certain conditions are true or false, evaluate expressions, etc.
\subsubsection{The Call Stack}
The \df{call stack} in the upper-left corner of the program window displays a list of currently active methods. The name of the currently executing method appears at the bottom of this list, the name of the method that called it is just above, and so forth. For example, if method \cd{main} called \cd{sort\_list}, which called \cd{move\_smallest\_to\_front}, which called \cd{move\_element}, the call stack would be: \begin{program} main sort_list move_smallest_to_front move_element \end{program} Additional methods may be listed above \cd{main}. These methods are either part of CodeWarrior or part of the operating system. Normally you will be interested only in the ones from \cd{main} down.
You can view the source code and local variables of any method in the call stack by selecting its name.
\subsubsection{Local Variables}
The upper right corner of the program window shows the local and global variables of the method currently selected in the call stack. The current value of each variable appears to the right of its name.
The values of simple variables, with types like \cd{int}, \cd{double}, and \cd{char}, are displayed to the right of the variable name. For arrays and structures, the memory location of the variable is shown and there is a boxed ``+'' to the left of the variable name. Click this button to see the components of the variable (array elements or structure fields). More complex data structures may contain fields that can be further expanded by clicking such a button.
\begin{note}[Note:] Uninitialized variables may appear to have nonsense values. For example, if an integer variable has not been initialized, something bizarre like -14853 might be displayed as its value. \end{note}
To view the value of a variable in a separate window, double click its name or select \mn{Open Variable Window} from menu \mn{Data}.
Other commands in menu \mn{Data} control how information about variables is displayed.
\mn{Show Types} displays the type of each variable along with its value.
\mn{View As...}\ allows you to set the type according to which a variable is displayed. This is primarily useful for machine level debugging.
\mn{Open Array Window} displays an array in a separate window. \key{Option}-double-clicking a variable name is a shortcut for this command.
To change the value of a variable during debugging, double-click its current value and enter a new one.
\begin{note}[Warning:] This changes the value of the variable only for the current execution of the program. To make a permanent change, you {\it must\/} change the original program. \end{note}
\subsubsection{Expressions}
You can evaluate expressions in the \df{expressions} window. Expressions may include program variables or Java operators, but not method calls. To enter a new expression, select \cn{\mn{Data}}{\mn{New Expression}}, type the expression and press \key{Return}. You can copy and paste an expression from the source program.
To modify an expression, double-click it and make the desired changes. Hit \key{Return} to display its value.
\subsection{When You're Done}
If you plan to run your program with the debugger again, quit your program (Java console window) but leave the debugger application running. Use CodeWarrior to make any needed changes. When you select \mn{Debug} again (\key{command-r}) the debugger will resume control of the program.
To run the program without the debugger, select \cn{\mn{Project}}{\mn{Disable Debugger}}. To resume debugging, select \cn{\mn{Project}}{\mn{Enable Debugger}} again.
Remember to quit the debugger when you are done: Select \cn{\mn{File}}{\mn{Quit}}. \end{document}