DEBUG - hints for debugging.

(Single Segment Pascal Only)

Normally if a Pascal program aborts, a traceback is printed showing all function and procedure calls. The names printed will either be the name of the subprogram being executed, or the subprogram or module that contains the executing subprogram. The line numbers printed in the traceback may be used to determine which inner subprogram is being referred to. For reasons not worth discussing here, if the program uses a PROGRAM statement instead of "procedure main", the mainline module shows up as ".optab" in traceback.

If the program makes use of the import/export separate compilation feature, the declaration module name will be used to refer to lines in the implementation module. If the program was loaded in batch or in TSS with the "-Tables" option, debugging tables are not available and the traceback will shown "??????" for the subprogram name. Again, the line numbers may be used to interpret the traceback.

It is possible for the program to run amok and destroy the traceback mechanism before causing a fault sufficient for the operating system to abort the program. Usually, specification of the "+Value" option will catch the error before this can occur.

It may also be possible to use the post-mortem debugger BOFF (included in the Software Tools package) to examine the abort file and obtain a traceback. BOFF can be used to obtain a traceback from an abort file after the original traceback has rolled off the screen. The BOFF traceback also includes the arguments of each procedure or function call.

Looping Programs:

If a program appears to be stuck in a loop, pressing BREAK will terminate the program and produce a traceback showing where the program was when BREAK was pressed. Pressing BREAK discards the contents of the terminal output buffer, so it might look like some write statements in the program were not executed. This is not so; the output was simply waiting in the buffer. The traceback shows where the program really was.

To help you detect programs that are stuck in loops and to prevent you exhausting the resources of your account by accident, the PASCAL command runs programs with a default 15 second time limit. If the program is terminated because it exceeds the time limit, TSS will write an abort file that can be examined with BOFF and the program will flush its terminal output buffer. This means that output from the last write instructions will not be lost (unlike the situation when you press BREAK).

Note that the GO command imposes no default time limit. Thus if you are using GO to run your program, you must use GO's "Time=" option to get the same effect.

You can specify a longer time limit using the "Time=" option of the PASCAL command. You can suppress it entirely by specifying a time limit of zero.

Separate Compilation:

If you are using the separate compilation facility, it is important to recompile every module that imports or exports a declaration module whenever the declaration module is changed. Failure to do this will result in any number of strange aborts (op faults, ipr faults, memory faults etc), because the modules compiled before and after the change will have different ideas about where the objects in the declaration module are found. This can result in transfers into the middle of nowhere, storing data on top of code, and other formulae for disaster.

General Hints and Recommendations:

Until your program is thoroughly debugged, always use the "+Value" option. This generates range checks on variables and initializes the stack to a value that should make errors manifest themselves in an obvious manner.

Restricting all integer variables to the subrange needed for the program is also a good practice. Used in conjunction with the "+Value" option, this will cause many errors to show up sooner.

You can reduce the amount of stack space needed by declaring variables and arrays that are global to everything outside of any procedure. You can cause a more meaningful traceback by declaring routines at the first level, rather than inside procedure "main". Note however that external names must be unique in the first six characters.

Interpreting Run-time Errors:

Memory-Fault
This error means that a program tried to reference an address outside its memory limits. The two most probable causes are a subscript out of range and use of an uninitialized pointer. The "+Value" option detects the out-of-range subscript and causes some uses of uninitialized pointers to produce memory faults. In the latter case, the traceback will point to the line in error.
Attempt to reference through NIL or undefined pointer
This error message occurs when a hardware fault tag fault happens. It is usually caused by indirecting through a pointer with the value "nil" or through an uninitialized pointer. The traceback will point to the line in error.

This message may also be caused by misdeclaring an argument of an external procedure to be a "value" rather than a "var" parameter. The clue here is that the traceback points to the supposedly debugged library procedure.

Stack overflow
By default, the run-time Pascal stack is 1000 words. The stack contains all the variables that are local to the currently active procedures. You should look at your program, decide the deepest call nesting, and add up the memory requirements along the path. Then recompile with the "Stack=" option specifying how much stack you need. If you decide that the amount of space you need is much less than the current stack size, check your program for endless recursion. Also look for accidentally passing a large array as a value parameter instead of a "var" parameter. Again, look at the traceback to help you differentiate between legitimate need for more stack and a recursion loop.
064-execute time limit exceeded
This error means the program exceeded either the default time limit of 15 seconds, or the value specified by the "Time=" option of the GO or PASCAL commands. Check the traceback to see where the program was executing and decide if the program was stuck in a loop or simply needed more time. The GO command can be used to rerun the program without recompiling. See the above discussion about looping programs for more information about time limits.

Copyright © 1996, Thinkage Ltd.