Small Basic: How to Debug
This article includes the following tips in the table of contents about how to debug the program written in Small Basic language. And also this article shows you real samples for debugging with published programs. This document is for the following versions of programs.
- Small Basic v1.0
- Visual Studio 2010 Express
- Visual Studio Express 2013
Display the Contents of Variables
When you find something wrong in your program, how do you find the cause? Small Basic IDE (integrated development environment) doesn't have ability such as variable watch. But in many cases, some variables have unexpected values in them. To find that, let's add TextWindow.Write() or TextWindow.WriteLine() to look in variables for debugging.
To show an array "arry", you can simply use TextWindow.WriteLine(array) or write code like the following code:
TextWindow.ForegroundColor = "Yellow"
num = Array.GetItemCount(arry)
index = Array.GetAllIndices(arry)
For i = 1 To num
TextWindow.WriteLine("arry[" + index[i] + "]=" + arry[index[i]])
EndFor
TextWindow.ForegroundColor = "Gray"
For text base program debugging, changing foreground color may help you to distinguish program original outputs and debugging messages.
For short value to display for debugging, you can use TextWindow.Title, GraphicsWindow.Title or GraphicsWindow.ShowMessage() also.
Write Debug Code Such as "If debug Then..."
If you wrote a subroutine to show such like an array for debug, that code will be useful also in the future. But, this code will be needed only when you debug. So it is a way to use debug flag to on and off your debug routines.
Maze 0.4 (PNC833-0) is a sample which has debug flag. Following line sets debug flag off. And debug = "True" will turn on the flag.
27.debug = "False"
The following lines call a subroutine to show array "cell" of the created maze as text.
61.If debug Then
62. DumpMaze()
63. TextWindow.WriteLine(title)
64.EndIf
The following lines slow down creating a maze to look and show variables and pause the program using TextWindow.Read().
229. If debug Then
230. Program.Delay(20)
231. EndIf
232. ' 2. Add the neighboring walls of the cell to the wall list.
234. AddWallToList()
235. If debug Then
236. TextWindow.WriteLine("iWalls=" + iWalls)
237. TextWindow.Write("nWalls=" + nWalls)
238. TextWindow.Read()
239. EndIf
And after debugging is completed, these lines are easily found (with [Ctrl]+F in Small Basic IDE) and removed. Actually, these routines are removed in Maze 0.5 (not published).
Write Test Programs for Subroutines
To write generic subroutines (for general-purpose) will help your productivity. In my case, some subroutines for colors, maths, mouse, and etc. are reused in many programs. But generic subroutines should be well tested and have no bugs. No (or less) bugs will be a prior condition for productivity.
To test your subroutines, it is a reasonable way to write a test program for them. The good test program will find bugs from your subroutines and make easy to check regression after debugging.
A program which calculates combination nCr for big n (CPQ608) has a test routine TestDiv() for a generic subroutine Div().
Following parameters were found with TestDiv() and caused the problem in Div().
'a = "434399216531770650390143258708"
'b = "6752306690329"
'a = "397896921587794748049229269710"
'b = "8642083658481"
Write List of Bugs
The following list was written when Shapes 1.1 (TLW744) was in debugging. When you write lots of code, you may happen to meet many strange behaviors in your program. If so, it will help you that you write a list that includes each phenomenon. Because there may be many different causes of phenomena. And after debugging, this list will be a good test set for your program.
- CalcOpposite() returns wrong value when shape re-sizing
cause: variable func was not be set for the routine - Pinches (small circles) remain after click out of shapes
cause: not implemented yet - Frame sometimes not appear when shape moving
cause: variable i didn't set as selected shape - Pinches sometimes remain when cut and paste
cause: duplicate as follows - Pinches don't redraw after copy
cause: pinches are not displayed after paste - The shape moves after mouse release
cause: needed to keep mouse released in mouse handler - Other shape size and position become wrong after color change
cause: unnecessary RegisterShapeData() called and broke variable i - Other shape selected after adding ellipse or triangle
cause: cancel adding procedure (when menu item clicked) set needless variable obj - Sometimes shape can't be moved
cause: mouse released flag should be cleared
Meaning of Error Messages
There are two types of error messages given by Small Basic. One is compiled errors. Another one is runtime errors. These messages help your development.
Compile errors appear under source code just after the "Run" button is clicked if your program has any syntax errors. The following picture shows errors of a program "Fifty" (BRQ733) :
Sorry, we found some errors...
11,28: The variable 'files' is used, but its value is not assigned. Are you sure you have spelled it correctly?
29,24: The variable 'buf' is used, but its value is not assigned. Are you sure you have spelled it correctly?
Numbers mean lines and columns of source code, and you can jump into the point in source program by double-clicking the error message. This kind of compile error messages show you what happened and some advice to fix them. In this case, errors happened because of lines with File.GetFiles(path) and File.ReadContents(filename) have been automatically commented out by Small Basic server.
On the other hand, a runtime error appears while a program runs but happens to meet trouble which makes the program stop. The following picture is a sample of division by 0 error message.
Value was either too large or too small for a Decimal.
at System.Decimal..ctor(Double value)
at System.Decimal.op_Explicit(Double value)
at Microsoft.SmallBasic.Library.Math.Remainder(Primitive dividend, Primitive divisor)
at _SmallBasicProgram._Main()
The list shown in the text box is called stack trace. This list shows you relations which subroutine calls which subroutine at the error. In this case, the stack trace shows that main part of the program calls Math.Remainder() and occurs error.
Use "Graduate" and Visual Studio Debugger
Despite writing many debug routines, some bugs may be too complicated to find their causes. As a last option, it will work for you to use "Graduate" button to convert Small Basic program to Visual Basic program. This allows you to use strong Visual Studio debugger to find causes of bugs originally in your Small Basic program.
Step 1: Install Visual Basic 2010 Express if you don't install yet.
Step 2: Push "Graduate" button and input folder name for converted Visual Basic program.
Step 3: Push [Next] or [Finish] buttons in Visual Studio conversion wizard. Program XXX.sb (or XXX.smallbasic) will be converted to XXXModule.vb.
Step 4: Select [PROJECT] [Add Reference] [Browse] SmallBasicLibrary.dll [Add] [OK].
Step 5: Rewrite from 'For i = 1 To n' to 'For XXXModule.i = 1 To n' to avoid scope error.
Step 6: Double click a source line to make the line as break point if needed.
Step 7: Push "Debug Start" button or [F5] key to start program.
Step 8: If program stops at break point, push "Step In (F8)" or "Step Over (Shift+F8)" to continue.
Step 9: See "Auto Variable", "Local" or "Watch" tab and confirm the values of variables.
Step 10: If you find a bug, push "Stop Debugging" button and rewrite your program with comment.
Step 11: Repeat from step 6 again.
If you confirmed a bug fix, go back to Small Basic IDE and fix program just as you did in Visual Studio.
There are some differences between Small Basic and Visual Basic syntax as listed below.
- Array : Array notation is arry[i][j] in Small Basic but arry(i)(j) in Visual Basic.
- Variable type : Small Basic variables are type Primitive so sometimes need type conversion such as 'If ans = CType("", Primitive) Then'.
- Boolean : Type Primitive can be used as boolean as follows:
clicked = true ' or false
If clicked Then
If clicked = CType(false, Primitive) Then - Array: Setting to two-dimensional array doesn't work in Visual Basic. So replace 'shape(5)("angle") = 90' as follows:
saved = shape(5)
saved("angle") = 90
shape(5) = saved - For block variable: For control variable will cause warning about for it's scope. To avoid that declare module name before the variable: (We don't need to change variables inside block. Only in For statement.)
Before: For i = 1 To 10
After: For FooModule.i = 1 To 10
Conclusion
These tips are outputs from programming Small Basic within the last couple of years but not everything. It is important to be creative with programming and debugging. If you find good way, please add the way into this article. Small Basic is very compact and a good language to learn programming with. It's easy and powerful.
Additional Resources
- Debugging Small Basic Apps in VIsual Studio - Blog post by Phillip Trelford
- Debugger Small Basic Extension - Forum post by LitDev
See Also
- Small Basic (en-US)
- Wiki: Small Basic Portal
- Small Basic Curriculum: Lesson 3.6: Debugging Aids
- Small Basic: Instructions to Graduate and Debug with Visual Studio