|
Chapter 11 |
Introduction
Debugger Control
STOP Commands and Breakpoints
Memory Windows
Variable Windows
Debugger Settings
Debugger Error Messages
Practical Examples
Debugger
Control
To be able to debug a program, you first have to move the window with the
source code to the front and then select the menu option 'Debug' from the 'Program'
menu. The program is then compiled in a special format, which enables the debugger
to monitor and control the program execution at any time. The following potential
error sources are monitored as well:
- Integer overflows with byte, integer, and long integer numbers. For example: A%=32768 or A%L=10^12 would trigger such an error.
- Floating point underflows and floating point overflows. These errors occur when the result of a calculation cannot be depicted in the applied number format (e.g., A#=10^100*10^250 or A!=10^-45).
- Divisions by zero.
- Illegal operations such as A#=LN(-1).
- BASIC stack overflow. This can happen, e.g., when sorting large fields or during recursive programming with large interleaf depths.
- In case of field variables, it is checked whether the specified indices are located in the range for which the field has been dimensioned, e.g., DIM A#(2,3):A#(3,2)=1 would trigger such an error.
If one of these errors occurs, an alert box is shown first describing the error. After leaving the alert box the Debugger Control appears. You can now open memory and variable windows and find out what caused the error. If it is not a fatal error, the program may continue; otherwise, it is always terminated when you try to continue.
Of course, there is a variety of other traps waiting for the programmer, which cannot be recognized by the debugger due to their nature (e.g., LPOKE 12,-1, or if you are using the Extension Library but have forgotten to add Extension_Init to the beginning of the program). Do not try this because it is sure to crash your computer!
For the debugger to be able to process all of these tasks, a table is created establishing a link between the source code and the object code generated by the compiler. The program can thus not be edited during the debugging phase. Therefore, do not think that your computer has crashed just because you cannot change your program any longer.
The program is started automatically after compilation is complete. The programs
generated with 'Debug' run somewhat slower than when using the menu option 'Compile
& Start' due to the many management tasks that have to be processed. However,
this should not come into play when searching for errors.
Note: If you are using the Lite or the Demo version
it may be that a program can be compiled normally but cannot be debugged. The reason
for this is the additional object code generated in the debugging mode, which results
in a program that is too long for the Lite or Demo version.
After the debugger has started your program, a small window opens containing the
Debugger Control. The window has 7 buttons, which may be used to control the progress
of your program. The control options are as follows:
[Stop]
Your program comes to an immediate stop if you click on this button. The window
with the source code also automatically scrolls to the spot where the program stopped
and marks this location with a small triangle. This function can also be called by
pressing [Ctrl]+[C].
Attention: If your program does not make any regular calls of COMPILER "EVENT" or EasyMesag (in the case of programming with EasyGem) the program can be stopped only by pressing [Ctrl]+[C].
[Continue]
This button can be selected only if a program has been stopped. When you click
on this button, the program execution is continued with the command to which the
small triangle is pointing.
[Step into]
This button can be selected only if a program has been stopped. When you click
on this button, only the one command to which the small triangle is pointing is executed.
If it is a procedure or function call, the program pointer jumps into the procedure
or function. The same applies to GOSUB commands.
Please note that functions can also occur in formulas. In that case, all functions
occurring in the formula are entered into.
If the procedure or function has been supplied by a library, the debugger does not enter the subprogram. This would actually serve no purpose since the program code in the library is not listed and you cannot monitor the progress of the program as it is.
Note: A few of the library commands use callback
functions, which you have to define yourself and which are thus not located in the
library (e.g., Uwin_Open from the EasyGem Library).
If you now call library commands using [Step into], the program pointer does not
jump into the library but could land in your callback routine if this is just now
being called from within the library.
Unless you intend this action, it is better to use the button [Single Step] to avoid
any such confusion.
[Step out]
This button can be selected only if a program has been stopped. It serves
to trigger a procedure or function without having to execute all commands within
the procedure or function in individual steps. To be exact, the program execution
is continued until the debugger meets up with a RETURN,
END_PROC, END_FN, or EXIT, which is located
at the same hierarchy level as the program pointer was when this button was clicked.
After the button has been selected, the program pointer is then located directly
behind the command used to call the procedure or function. The same applies if subprograms
are called via GOSUB commands.
Note: If you are using this button while the program pointer is not located in a subprogram, it will have the same effect as [Continue], because no RETURN commands are located in the uppermost hierarchy level.
[Single Step]
This button can be selected only if a program has been stopped. This function
is similar to the function of the [Step into] button with the one difference that
subprogram calls are always interpreted like BASIC commands and therefore is never
be stopped in subprograms.
[Animation]
This button can be selected only if a program has been stopped. This will
continue the program in slow motion. The standard settings ensures that the debugger
executes max. one command per second. This interval can also be changed using the
dialog box 'Debugger Settings'.
[Terminate]
This button can always be selected. It may be used to terminate the program controlled
by the debugger at any time. This closes the window for the Debugger Control automatically.
Attention: A few Omikron Basic commands wait
for user input before continuing the program. Since the debugger can halt a program
only in-between two commands but not actually in the middle of a command, the debugging
command in these cases does not become effective until the command has been concluded.
These are the Omikron Basic commands INPUT, LINE INPUT,
FORM_ALERT, and FILESELECT or FSEL
INPUT, as well as the EasyGem commands Easy_Alert,Easy_Fsel,
Easy_Fnav, and Pick_Color.
For example, if your program is in an INPUT instruction
and you click on [Terminate], the program is not terminated until the user has exited
the input instruction with [Return].
If you stop your program using the Debugger Control, the spot where the program stops is more or less selected at random. But there are two other possibilities, which will halt the program in a specifically selected location.
STOP Command
Even before starting your program with 'Debug' just insert a STOP
command at the location where the program is to stop. Those who used to work
with BASIC interpreters are probably familiar with this method. The STOP command
halts a program without deleting variable and memory contents.You can then continue
the program in a targeted manner using the Debugger Control.
Attention: The STOP
command functions only if the program has been started with 'Debug'. A normally
compiled program using the STOP command will lead
to an error message with subsequent termination of the program.
Breakpoints
Breakpoints are additional stopping points, which you can include in your
program. Contrary to STOP commands, breakpoints cannot
be set until the program has been started with 'Debug'. Just pull the source code
window to the front, press the [Ctrl] key, and click on the spot in the source code
where the breakpoint is to be set. A small ellipsis appears in the color of the commentary
lines. As soon as the program pointer is now running across this spot, the program
is halted and you can use the Debugger Control for a detailed analysis. If you click
on a breakpoint again, it is removed.
You can set as many breakpoints as desired. Contrary to STOP
commands, breakpoints are only effective during a debugging phase. After the
program is finished they are automatically deleted. They also cannot be copied to
the clipboard or saved. If you would like to insert permanent breakpoints into your
program you have to use the STOP command.
Note: You cannot set breakpoints in all locations of a program because some lines, such as a commentary line, are skipped by the compiler and some BASIC commands serve only to structurize but do not generate an object code. In these cases, the breakpoint appears in the next possible location before the position on which you clicked.
Attention: If you are using the EasyGem Library
or have programmed your own event handling routine, your program cannot restore the
contents of windows once it has been halted by the debugger.
This does not apply to Omikron Basic output windows. These are managed by a small
assembler program, which continues to run even when the BASIC program has been halted
by the debugger.
Memory Windows
Memory windows can be opened with the menu options carrying the same name from the
'Program' menu. Memory windows are used to view the content of RAM memory.
There is an input line in the upper left corner of the window, which may be used
to specify at which logical address the memory content view is to start. The address
can be prefixed and indicated in all number systems supported by Omikron Basic (e.g.,
$A6553 or 123456).
Pushing [Return] shows the memory content starting with the specified address.
If the specified memory range does not exist, an error message appears and nothing
is shown.
The type of display can be set via the Debugger Settings.
Variable Windows
You can enter the names of variables into the variable windows. Their
content is then shown in the same window. For string variables the length of the
strings are indicated as well.
Only constants or individual variables may be used for the indices of field variables
(e.g., A#(X,Y) or A#(1,3)).
As long as a program has not been started with 'Debug' the content of variables is,
of course, 0 and an empty string for strings.
The number system to display the variable content can be set with a prefix. For example,
the input of $Tex$ would output the content of the
string Tex$ as a byte sequence in hex numbers and
not as a character string. Similarly, the input of %A
would result in the variable content A as a binary
number. According to the default setting, the output of numerical variables is always
in the form of decimal numbers and strings are always output as character strings.Strings
can also be output as a decimal byte sequence by prefixing with the number symbol
"#." This is of special interest if one
is interested in the ASCII values of a string.
Block functions also work in variable windows. Instead of typing in the desired variables,
you can transfer them from the program window using 'Copy' and 'Paste'.
Variable windows can also be saved, reloaded, or printed. The format for saving is
ASCII. If they are reloaded, the variables are assigned to the currently topmost
program window.
If a variable does not exist or a field element is not located within the dimensioned
range, the line is marked in red to indicate an error line (red is the default setting).
A variable window always refers to a specific program window. If the window is closed,
all linked variable windows are automatically closed as well, because the variables
contained in the program window are no longer defined.
Modifications to the variable windows can be set in the Debugger
Settings dialog.
Debugger Settings
Of course, it is also possible to individually configure all of the important debugger
functions. To configure the debugger use the dialog you find in the 'Mode' menu under
'Settings>General-Debugger'. A detailed description can be found in Chapter 3,
Debugger.
The dialog box can remain open while working with the debugger so that you can change
the animation speed during a running animation process, for example.
Error Messages of
the Debugger
The program "Program Name" has unexpectedly quit.
In some cases it can happen that a program to be debugged is terminated spontaneously.
In these cases it is no longer possible to send a message to the debugger. The debugger
in turn is not informed of the termination. If you now still try to apply debugger
commands to the terminated program, you will receive this error message.
The addressed memory does not exist.
This error message appears if you try to display a non-existing memory range.
After we have described the debugger components, we would like to illustrate how
to use the debugger by using some examples. The sample programs are equipped with
line numbers for easier line reference. The line numbers are not required to run
the program. All variables without postfix are of the long integer type according
to the Omikron Basic editor default setting. If you have modified this setting, you
have to consider this when transferring the program code.
The examples listed here are located in the folder DEMO:Debugger (Demo).
Example 1:
Open a new program window and transfer the following program to an empty window using the 'Copy' and 'Paste' functions. We have added an error to example 1, which we now will find using the debugger.
|
Start the program first with 'Compile & Run'. The program is to calculate the prime numbers between 11 and 120, and it is assumed that the primes < 11 are already known. As you can see, the program runs normal and does not issue any error messages, but it also calculates incorrectly because the number 49 is marked as a prime even though it is divisible by 7.
Quit the program and restart it once more using the menu option 'Debug'. The program
stops on line 35 and issues the error message "integer overflow." Click
on [OK]. You are now in the debugger. The position where the program stopped is marked
with a small triangle.
To ascertain the type of error that occurred open a new variable window. Enter I, J, and Primes(J)into
the window and press [Return] after each input so that the variables appear in different
lines. As can be seen, I has the starting value 2,
J the end value 3,
and Primes(J)=0, so that the operation I
MOD Primes(J) is not defined and leads to the "Integer overflow."
Just one glance at line 22 shows that an incorrect end value is specified for the
control variable J in the READ
loop (2 instead of 3).
Now click on [Terminate] in the Debugger Control. Then add a STOP
command to line 18 and correct the wrong end value in line 22 (change 2 to 3).
Then restart the program with 'Debug'. The program is now halted directly behind
the STOP command. Primes(J)
is depicted as an error line in the variable window. This is because this field has
not been dimensioned yet. Now advance one step at a time by clicking on [Single Step]
in the Debugger Control. After the DIM command in
line 20 has been executed, Primes(J)=0 is displayed
correctly in the variable window. If you now proceed with the READ
loop step by step until finished, you can view on the monitor how the prime numbers
are read into the field Primes() one after the other.
At the end of the loop, Primes(J) is again depicted
as an error because J is now 4 and Primes(J)
has only been dimensioned up to three.
Once you reach line 25 you can decide whether you want to execute the procedure
Display_Numbers as a command with [Single Step] or
if you would like to jump into the procedure with [Step into]. We decided to use
[Step into] to demonstrate the functions of the debugger.
Since PRINT output is directed to the Omikron Basic
output window from within the procedure Display_Numbers,
you should move aside the program window so that you can see the output window.
Of course, now you could execute all commands in the procedure in individual steps
but since nothing spectacular is happening here we would like to take this opportunity
to demonstrate another function of the debugger. Click on [Animation]. The debugger
now executes all commands in slow motion. You can now track how the program pointer
progresses through both of the loops and how the numbers are written to the Omikron
Basic output window. Once you have seen enough, click on [Stop]. The program stops
at the current location. If you now click on [Step out] all commands within the procedure
are executed and the program is not stopped until line 26, behind the procedure call,
has been reached.
Now keep the [Ctrl] key depressed and clicked on the FOR
in line 31 with your mouse. This sets a breakpoint in front of the FOR
depicted as an ellipsis. Click on [Continue]. The program pointer stops exactly on
the breakpoint. If you now click on [Continue] several times, you can watch how every
individual number is examined to see if it is a prime number. The variable window
now shows the variable values of I and the other
variables and track in the Omikron Basic output window how the individual numbers
are marked as non-primes.
Now keep the [Ctrl] key depressed and clicked on the breakpoint in line 31. This
removes the breakpoint. Set a new breakpoint in line 43 behind the THEN.
Then click on [Continue]. The program will now always stop when a new line is started.
Remove the breakpoint again and click on [Continue]. All non-primes are marked and
the program is in the waiting loop in line 45.
Click on [Stop]. The program halts in the waiting loop. This works only because the waiting loop contains an EVENT call (COMPILER "EVENT" or Easy_Mesag with EasyGem programming). If your program is in a loop without any EVENT calls, you can still stop the program using [Ctrl] +[C].
Click on [Terminate]. Eratosthenes is terminated, the Debugger Control is hided, and you can edit the source code again to calculate additional prime numbers, for example.
Example 2:
The second example does not contain any errors and serves only to illustrate the debugger functions further. Again, open a new program window and transfer the following program to an empty window using the 'Copy' and 'Paste' functions. Then you have to load the Extension Library with the menu option 'Merge LIBRARY'.
|
Then start the program with 'Debug'. As expected, it stops in line 22, directly
behind the STOP command. Now progress with [Step
into] until you reach line 58. Open a new variable window and there enter $Adr.
After pressing the [Return] key, the address of the memory block allocated in line
57 is depicted in the variable window as a hex number.
Open a new memory window and then the debugger settings using 'Mode/Preferences/Debugger'.
In the now opened dialog, set 'Bytes per group' to 1, 'Bytes per line' to 8, 'Display
bytes as' to decimal and 'Show character string' to off. Then click on [Execute].
The content of the memory window is now depicted in the form of three-digit decimal
numbers. The character string display disappears. Now transfer the value shown in
the variable window for Adr to the address field
of the memory window using 'Copy' and 'Paste' and confirm with [Return].
If you now proceed through the program in individual steps, you can follow in the
memory window how the random numbers are written to memory.
Return to the debugger settings and set the 'Animation delay' to 100. Then confirm
with [Execute]. Make sure that the memory window and the window with the BASIC program
remain visible and then click on [Animation] in the Debugger Control. You can now
observe how the random numbers are written to memory every tenth of a second.
Once you have seen enough, click on [Stop] and then on [Step out]. This causes you
to leave the procedure, and then you are located behind the call in line 25.
Set a new breakpoint in line 39 by pressing the [Ctrl] key and click in front of Set_Print_Size with your mouse button to then continue the program. The program stops in line 39. Now click on [Step into]. Although the next item to be executed is a procedure, the program pointer jumps to the next line because the procedure Set_Print_Size is located in a library.
Now bring the Omikron Basic output window to the front. Then click on [Animation]. You can now see how the statistical data are written to the Omikron Basic output window.
Example 3:
This example is a very simple program to easily show which values from MOUSEBUT
and INKEY$ are returned if certain keys are pressed. Again, open a new program window
and transfer the program to an empty window using the 'Copy' and 'Paste' function.
|
Go to the debugger preferences and activate 'Permanently update variable windows'. Then click on [Execute]. Open a new variable window and enter the variables %Mb and %Kbrd$.
Then start the program with 'Debug'. If you now press the mouse button alone or together with any modifier key, you can immediately see in the variable window which bits are set. The same applies to all normal keys of the keyboard. The thus generated ASCII codes, virtual key codes, and modifier key codes are displayed in Kbrd$.
Support | Ordering | Start | Home: http://www.berkhan.com |
© 1997-2001 ![]() |