• Keine Ergebnisse gefunden

Stepping Through Your Program

Im Dokument Turbo Pascal® (Seite 131-135)

Now let's look at how to actually use the debugger.

The simplest debugging technique is single-step tracing. You already tried this in an earlier example we gave you. If you have a program displayed in the Edit window, you must compile it first before beginning your debug session. You can do this by choosing Compile/Make (F9) or Run/Trace Into (Fl). F9 will make the program; F7 will both make the program and place the execution bar on the first line in your program. You can then execute that line by choosing Run/Trace Into (Fl) or Run/Step Over (FB).

The difference between Trace Into (F7) and Step Over (FB) is that F7 traces into procedures and functions, while FB steps over those subroutine calls.

These commands also have a special meaning at the begin statement of the

rr'~in progran1 if the program uses units ,Alith initialization code. !n this case, F7 will step into each unit's initialization code, allowing you to see how each unit sets itself up. FB will step over the initialization code, leaving the execution bar on the next executable line after the begin.

When you step using F7 or FB, the User screen may be displayed, usually briefly (unless the program is waiting for input), and the program text is displayed again, with the execution bar on the next line to be executed.

When stepping into (with Run/Trace Into or Fl) a procedure or function compiled with Options/Compiler/Debug Information set to On, Turbo Pascal will load the source code and position the execution bar at the beginning of the procedure or function.

If you encounter another procedure or function call, then you can trace into that routine, as far as you care to go. Once you reach the end of a routine, you are returned to the procedure that called it.

Consider the following example, TEST.P AS:

{$Dt,Ltl

If you start debugging this program by pressing F7, the program will be compiled and the execution bar will highlight the second begin statement (on line 16).

Pressing F7 continually will step you through the main body until you reach the line calling Swap. When you press F7 again, the execution bar moves to the begin statement in Swap. From there, you step through each statement in Swap until the execution bar reaches the closing end. Another press of F7 and you're back in the main body of Test, with the Writeln highlighted. Another F7 executes that line and leaves you at the closing end of Test. One more Fl, and the program is done. Notice the execution bar is gone.

You might wonder why you need to "execute" the begin and end state-ments of the main program. The explanation is that the execution bar only highlights lines that generate code. Executing the begin statement calls any initialization code, including initialization code from any units your program might be using. This means you can actually step through your

unit's initialization code (use F7 to step into your unit's initialization code and FB to step over it.) Likewise, executing the final end statement causes your program to call the chain of exit procedures. If you've installed your own exit procedure(s), then they are called as well (although you must set breakpoints within them to debug them).

Let's look over TEST.PAS. Why did F7 step over the Write and Read statements but step into Swap? Because Turbo Pascal could find the source code for Swap, but Read and Write are part of the run-time library and their source was not available (and, for that reason, we compiled them with Debug Information set to Off). Suppose you want to step through the main body of Test, but don't want to trace through Swap? Is there a way to force the debugger to treat Swap the same way it treated Write, Readln, and Writeln?

Yes, by using Run/Step Over (FB). This acts just like Run/Trace Into (F7), with one important difference: If the line contains any procedure or function calls, you don't trace into them; they are executed just as if they were system calls. This lets you avoid tedious tracing through subroutines that work just fine or that you want to avoid for now. Of course, if you have a breakpoint within that routine, the debugger will halt at that line.

If, while in TEST.PAS, you press FB when the execution bar is on the line containing the call to Swap, Swap is called and the execution bar is positioned on the next line (calling Writeln).

Now, consider the following (incomplete) sample program:

{$D+,L+}

program TestSorti const

NLMax = 100i type

NumList = array[l •• NLMax] of integer;

var

List : NurnListi I,Count : word;

procedure Sort(var L : NurnListi C : word);

begin

{ sort the list } and; { of proe Sort }

begin

Suppose you're debugging the Sort procedure. You want to trace your call to Sort, including checking the values within List before calling it. However, it gets tedious stepping through that first for loop 100 times as it initializes List. Is there some way you can get the loop to execute without having to single-step each line?

Yes. In fact, there are a few ways. First, you could put it in a separate procedure and press FB when you get to it, but that's a bit drastic. Second, you could set a breakpoint within your program. We'll explain what breakpoints are and how they work in just a minute.

Finally, you could use the Run I Go to Cursor command (hot key F4). Just move the cursor to the line calling Sort, then press F4. Your program will execute until it gets to the line containing the cursor. The execution bar will move to that line; you can then start tracing from there, in this case by pressing F7 so that you can trace into Sort.

Run I Go to Cursor (F4) works through multiple levels of subroutine calls, even if the source code is in another file. For example, you could place the cursor somewhere within Sort and press F4; the program would execute until it reached that line within Sort. For that matter, Sort could be in a separate unit, and the debugger would still know when to stop and what to display.

There are three cases where Go to Cursor (F4) will not run to the line containing the cursor. The first is where you have the cursor positioned between two executable lines; for example, a blank line or a comment line within a code block. In this case, the program will run to the next line containing executable statements. The second case is when you have the cursor positioned outside the scope of a procedure block; for example, on the program statement or variable declarations. The debugger will tell you there is "no code generated for this line." The third case is when you position the cursor on a line that will never gain control; for example, the line above the execution bar (assuming you're not in a loop) or the else part of a conditional statement when the if expression is true. The debugger will behave as if you had chosen RunlRun (Ctrl-F9); your program will run until it terminates or until a breakpoint occurs.

Let's say that you trace through Sort for a while, then want the·program to finish executing so you can see the output. How would you do this? First, you could move the cursor to the final end statement in the main body of the program, then choose Run/ Go to Cursor (F4).

More simply, you could choose Run/Run (Ctrl-F9). This tells the debugger to let your program continue normal execution. Your program will then run until it ends or hits a breakpoint that you've set, or until you press Ctrl-Break.

Im Dokument Turbo Pascal® (Seite 131-135)