Rapid-Q Documentation by William Yu (c)1999, Appended by John Kelly Appendix C: Trouble Shooting

How to debug your programs

In most cases, it's either a typo, or you're trying to use a function which is not supported under Rapid-Q. This occurs most often when you don't have $TYPECHECK ON. I can't stress this enough, unless you've used Rapid-Q for awhile, I strongly encourage everybody to turn this directive on. Rapid-Q has a very poor checking mechanism, and relies heavily on the programmer to write proper code. For Example:
    PRINT SPC(10)
SPC is not supported in Rapid-Q (in QBasic, SPC just skips spaces). If typechecking is off, the above statement is perfectly valid. SPC is a variable, initialized to 0, and (10) has no effect (ie. the number 10 is pushed on the stack, but no operation is done), so the above output will be 0.

Why didn't my SUB or FUNCTION run? Why didn't my code work?
When inside a SUB or FUNCTION, if RapidQ comes to a statement that fails, the program will EXIT the SUB or FUNCTION without warning you. To make sure your SUB/FUNCTION really was completed, put a statement like SHOWMESSAGE "End of Sub reached" at the end to make sure it really ran the subroutine. Otherwise there is a problem with your code that causes the program to leave your sub. This can also happen outside of a SUB/FUNCTION, but you probably will get a program that doesn't run.

Passing by reference
Only QObjects, Arrays, and Variants are passed by reference, all other variables are passed by value. To pass a variable by reference, you can either explicitly specify this by adding BYREF to your parameter list, or prepend an @ symbol to any variables you want passed by reference when calling the function. Do not use the @ symbol for Arrays, Variants, or QObjects since they are passed by reference by default. Read more about this in Chapter 3 or Appendix C: Procedures. Typechecking is done only for Arrays, Variants, and QObjects, since you can't pass an array of integers to a SUB that expects an array of doubles. You should get an error message if you try this, however, for all other variables which are passed by value, NO checking is done. Which means you could easily pass an integer to a SUB expecting a string. So becareful that you know the type of parameters for your SUB/FUNCTION, since Rapid-Q won't complain. Also make sure if you have DECLARE SUBs, that your SUB will have matching parameters, including matching parameter names.

Using Undocumented features
Rapid-Q has some undocumented features, most of which are in a beta-like stage. You can embed SUBs or FUNCTIONs but they can only be one level deep, and there are some consequences with using them. If you don't know what an embedded SUB looks like, take this for example:

    SUB MySub
      DIM I AS INTEGER

      SUB MyChildSub (X AS INTEGER)
        DIM N AS DOUBLE

        PRINT "In Child Sub"
      END SUB

      CALL MyChildSub(100)
    END SUB
There are some special issues involved, such as all variables are local to the SUBs that follow. Meaning, the variable I is local to SUB MyChildSub. Also, since Rapid-Q doesn't actually clean things up, you can actually call MyChildSub in your main program as well. 
One other feature which might interest people is postfix ++ and --
    DIM I AS INTEGER

    I++           '-- same as I = I + 1
    I--           '-- same as I = I - 1
    I -= 10       '-- same as DEC(I, 10)
    I += 15       '-- same as INC(I, 15)
Arrays are a special case, anything but Arrays can be incremented/decremented. Rapid-Q doesn't do any optimizing, so the above code and the given translation runs exactly the same. The boundaries of an array are not checked.  

Other errors
If you're using Unix or Linux, try using gdb, sometimes it will give you some useful information, but most of the time it's not really that helpful in this kind of setting. 

Useful hints:
1) Use 'Print' and 'ShowMessage' and add a number to allow multiple debug break points. Comment them out when bug is solved. 
... 
Print 1 ' Or ShowMessage ("1") 
... 
Print 2 ' Or ShowMessage ("2")
... etc.


2) For long loops and more complicated problems, an easy solution is to use QDebug. It is asy to add and remove, doesn't need string conversion, puts up a Edit form you can copy to clipboard, scroll through results, etc. You can easily close the form, and keep going. There is no size limit when debugging a large loop

$INCLUDE <RapidQ2.inc>
DIM d AS QDebug
... code
d.print "check here", myNum, S$, Arry(Num) 'etc.

to remove, search d.print -- so easy.

3) Put a single additional QEdit on a form and in every sub routine (or part of a routine) change the text of that QEdit to show where in the program it is. When something goes wrong you  have a reasonably good idea where the problem is to be found. After debugging set the QEdit to invisible. And of course if something else goes wonky turn it back on again.

4) I use status report modules, at the end of my coding, as a developemental tool. It works well as a debugging tool as well. Also see (http://tech.groups.yahoo.com/group/rapidq/message/32176)







Contents