Professional Documents
Culture Documents
0 Debugger Introduction
A debugger is an efficient, flexible, and easy-to-use tool for viewing a program as it executes. It is superior to sprinkling output statements throughout a program. A debugger will allow you to stop program execution, view and modify variable values, and re-run the program from the point it was stopped. All this can be achieved without modifying the program itself. This article will serve to get you started with the Turbo C++ debugger. Because this article is only meant as an introduction, some of the more advanced features will not be discussed here; the interested programmer should refer to the on-line documentation or the reference manual for more information. On-line documentation may often be read by highlighting a menu item (using the up-arrow or down-arrow keys) and pressing F1, by choosing Help within a dialog box, by highlighting a dialog box item (using the Tab key) and pressing F1, or by using the Help menu. When reading Help text, you may often get additional help on specific features by ``clicking'' highlighted words in the text and then choosing the Cross ref button in the Help dialog box.
Debugging Actions
The most common debugging actions are single-stepping or running (from the beginning or from the last statement executed) a program, setting and using breakpoints, and looking at and modifying variables. Let's look at each of these in turn. Note that many of these actions have ``short-cut'' keys associated with them. You can use the short cuts to avoid opening menus to choose actions.
You are probably most familiar with using Run|Run to start your program from the beginning. However, Run|Run is really used to start your program from the point of last execution. Only if the program had completely finished or was aborted does Run|Run pick up at the beginning. There are two ways to single-step (execute only one statement at a time) your program. Run|Step over executes the next statement (this is the statement highlighted by the run bar), treating subroutines (function or procedure) as if they were a single statement. Thus, you will not be able to watch the individual statements of your subroutines execute. Run|Trace into executes the next statement, treating subroutines as if they were collections of statements. With Run|Trace into you can watch your subroutines execute line-by-line. This will generally only work for subroutines which you write. You cannot trace into library functions. Anytime you would prefer to return to normal execution rather than single-stepping, choose Run|Run. If you are in the middle of your program's execution and want to return to the beginning, select Run|Program reset. If there is no run bar (i.e., you are at the very beginning of your program) you may single-step to start the program at its first statement (i.e., the first statement of main()). How do you determine whether to use Run|Step over or Run|Trace into? Firstly, you need to know that you can switch freely between the two. Once you start using one of them, you may still use the other. Secondly, the choice between the two should be governed by how much confidence you have in any subroutines which would be executed in the next statement (if there are no subroutines in the next statement, then there is no difference between Run|Step over and Run|Trace into). Run|Go to cursor is a primitive breakpoint, so I won't discuss it; see the on-line documentation.
Going Further
As mentioned previously, the on-line documentation provides detailed descriptions of all the debugging commands I've touched on here. The only debugging command which I haven't mentioned so far at all is for displaying the call stack. The ``call stack'' is a listing of the currently active subroutines. In Turbo C++ the call stack is displayed by choosing Debug|Call stack.