CHAPTER 13

TIPS ON DEBUGGING


By now you have probably tried a few programs of your own, and been disappointed when they wouldn't work. Don't be discouraged; even professional programmers can rarely get a new program to work on the first try. Here are some tips to help you ferret out the bugs hiding in your program.


ERROR MESSAGES


When you run your program, the Sorcerer looks for certain errors, when it finds one, it stops the program and prints an error message. The message gives the line number of the instruction that caused the problem and the error code, of the error.

The error codes are explained in Appendix D. Be especially watchful of SN errors. Incorrect punctuation, a space where none should be (or no space where there should be one), incorrect spelling or other typographical errors may stop execution of your program.

Error messages do not point out problems in logic The Sorcerer is very literal. It does exactly what you tell it to do. You may not, however, have told it what you thought you did.


PROGRAM DOCUMENTATION


You'll have a lot less trouble tracing the logic of your programs if you sprinkle them liberally with REM statements. Put in a remark at every step explaining exactly what's supposed to be happening at that point. When it comes time to run your program, if you find that so many REMs make it unwieldy or unnecessarily slow down the program, save a version on cassette tape with all the REMs in it, remove all the REMs from the version in memory, and run that. Save both versions. You'll be surprised when you come back later to old programs how much help adequate documentation is in helping understand what's going on.


MODULAR PROGRAMMING


Use modular programming in large programs. Write programs in separate sections. Work on each section until it does what it's supposed to. Keep things together. Put all the print routines together, all the data statements at the end, all the subroutines in a group, and so on. All branching should go in a generally downward direction. Conditional and unconditional branches should not send the program jumping all over the place, back and forth, weaving in and out, till it becomes a Gordian knot.

Some things to watch out for: You shouldn't jump out of a FOR ... NEXT loop until the loop is through, unless necessary. (Better to say FOR X=1 TO Y then to say FOR X=1 TO 100 with the requirement that IF X=Y THEN <line number>.) Never branch into a FOR ... NEXT loop (unless that's where you came from). Make sure you don't have a statement which sends the program away from (or skips over) an important statement in such a way that it can never get there. Make sure that variables are properly initialized. If you use a variable over again, make sure that it doesn't still have its previous value (unless that's what you want).


TRACE STATEMENTS


Wherever you suspect trouble in a program-and probably in many places that you don't-put PRINT statements that say their line number and what's supposed to happen at that point and the values of all variables. You can remove these statements later when your program works.

Example

105 PRINT "LINE 105. THIS SHOULD FOLLOW THE DECISION"
106 PRINT "ON WHETHER X IS AN INTEGER OR NOT. HERE"
107 PRINT "A SHOULD=0. A IN FACT=";A;"B=";B;"C=";C
108 PRINT "AFTER THIS SECTION THE PROGRAM SHOULD JUMP"
109 PRINT "TO LINE 200."

205 PRINT "LINE SHOULD HAVE COME FROM 120."
206 PRINT "A=";A;"B=";B;"C=";C;"X=";X

Put STOP statements at the end of questionable sections to see if the program ever gets there. When a program stops for any reason (including your hitting CTRL C ) you may use direct mode PRINT commands to examine variables. You may wish to look at the amount of free space you have left or how much string space remains, or you may print out an entire array to see if it has been properly filled. If you make no change in the program, you can resume execution with the command CONT. Otherwise, use a direct mode GOTO to the point you wish to resume the program, or use the RUN <line number > command. (Be careful, RUN < line number> resets all variables and arrays to zero.)


DEBUGGING SUGGESTIONS


Other suggestions. If your program is supposed to handle data, try it first on very simple data-nice round numbers and short, simple strings.

Do computations by hand (or use your Sorcerer in direct mode as a calculator) and find out what value each variable should have at each line of the program. Then when your diagnostic traces give you the values of variables, you can compare them with what they should be.

Trace through the logic and see which branches the program is supposed to take when it has to make decisions. Again, your removable PRINT statements will tell you if the program goes where it is supposed to. Be suspicious of any such PRINT statement that regularly fails to report as you run the program, or of any that shows up too often.

You might try temporarily replacing INPUT statements by DATA and READ statements or LET statements. This may save your having to type in the same data on each trial run. Alternatively, you might try temporarily replacing READ or LET statements by INPUTs, so that you can change the data more easily on different runs of the program. These INPUT statements should have prompt strings telling their line numbers and what data they expect.

If you construct your program modularly, try running it a section at a time. Debug each section, and then combine sections, one at a time, like building blocks.

There are a few special commands and functions you will find helpful for debugging, once you become familiar with the Sorcerer's machine language and inner workings. These are listed at the end of Appendix B.


Table of Contents | Prev | Next

The Trailing Edge