Trace and debug

Discussions about the BBC BASIC language, with particular reference to BB4W and BBCSDL
Ivan
Posts: 127
Joined: Tue 07 May 2019, 16:47

Trace and debug

Post by Ivan »

I am now passing 80 proceduces or functions in my program and have some troubles to keep track of everything.

I find the trace in v6.12a hard to use.

Is it possible to trace in such a way when an error happens so I can produce a trail or something?

Can someone point me in the right direction...
BBC Model B - 1984-1989. 6502 assembler, Unicomal 1988-1994, Some C and C++, Pascal 1990-1994. Bought a copy of BBC-BASIC 2007, but started to program at a daily basis 2019. C++ in 2021.
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Re: Trace and debug

Post by KenDown »

I don't believe that it is possible to produce a trail - though I am willing to be corrected. In any case, you would have to have line numbers and most of us (I think) use the brilliant feature of dispensing with line numbers.

If you have the ability to have your program's output and the program listing side-by-side - having two monitors is brilliant for this - then when your program crashes, the offending statement will be highlighted. The highlight disappears as soon as you close the program window (which you have to do in order to make any changes in the program).

However before closing the program window you should take advantage of the highlight to try and PRINT a few variables to see if they have the expected values. For example, if you have a loop which should end when a variable reaches -10 and you PRINT that variable and discover that it has the value of 1234567489 you will know where the problem lies!

The annoying thing is that often you cannot PRINT anything in the program window - every time you press a key you get a beep! The solution, simple but tedious, is to minimise the program window and then select it from the bar at the bottom of the screen and suddenly you have a cursor and can type into the window.

Another technique - and I apologise if I am instructing my grandmother on how to suck eggs - is to introduce artificial breaks in the program. STOP is one way, but I find that it doesn't always bring the program to the sort of crashing halt I want. So I use the keyword RUM (which is not a keyword at all, of course) and that stops the program in its tracks and then I can PRINT and otherwise explore that things are doing what they should.
RichardRussell

Re: Trace and debug

Post by RichardRussell »

Ivan wrote: Sun 01 Mar 2020, 20:53Is it possible to trace in such a way when an error happens so I can produce a trail or something?
If you're looking for the kind of stack traceback that a compiled language can sometimes provide, you're out of luck. Interpreters generally don't preserve the information necessary for such a report. But on the other hand I've been programming in BBC BASIC for more than 38 years, with my programs often having thousands of lines, and very rarely have I found debugging difficult.

It would be helpful if you could explain what general class of error it is that you are trying to track down. In my own experience the vast majority of common errors are typos, which are obviously easy to detect and correct. The most problematic kinds of faults are those which don't actually result in an error being reported at all, but cause the program to behave incorrectly.

BBC BASIC has a lot of tools to help with debugging. The first thing I do, before ever running a program, is to scan it with the Cross Reference utility and look at all the warnings. Some will be just that, and can be ignored, but commonly that utility will draw attention to a fault which could have been quite tricky to identify at run time.

When it does come to running the program, I will use whatever tool or combination of tools seems most appropriate for the problem I am encountering. That may be numbering the lines and using the TRACE statement, single-stepping and using the List Variables utility, or adding debugging statements into the program. One of my favourite techniques is to display debugging information in the title bar, because that's always visible:

Code: Select all

      IF DEBUG SYS "SetWindowText", @hwnd%, mydebuginfo$ : REM BB4W
      IF DEBUG SYS "SDL_SetWindowTitle", @hwnd%, mydebuginfo$, @memhdc% : REM BBCSDL
I will occasionally even resort to creating a log file:

Code: Select all

      IF DEBUG THEN PROClog(mydebuginfo$)
      ...
      DEF PROClog(info$) : LOCAL log%
      log% = OPENUP(LogFile$) 
      IF log% = 0 log% = OPENOUT(LogFile$)
      PTR#log% = EXT#log%
      PRINT #log$, info$ : BPUT#log%, 10
      CLOSE #log%
      ENDPROC
RichardRussell

Re: Trace and debug

Post by RichardRussell »

KenDown wrote: Mon 02 Mar 2020, 07:52If you have the ability to have your program's output and the program listing side-by-side
You always have that ability, unless your BASIC program is running in a (non-resizable) full-screen mode. I never run the IDE maximized, but even if you choose to do so you can always switch it to windowed for that specific purpose.
The highlight disappears as soon as you close the program window (which you have to do in order to make any changes in the program).
Needing to close the program's window before you can make any changes to its code in the IDE is specific to BB4W, you don't need to in BBCSDL. Bearing in mind that this forum supports both, it would generally be helpful to say what version you are referring to when they behave differently.
The annoying thing is that often you cannot PRINT anything in the program window - every time you press a key you get a beep!
Getting a beep either means that the keyboard buffer has filled up, or that there is no window which currently has input focus.
STOP is one way, but I find that it doesn't always bring the program to the sort of crashing halt I want.
That's not correct: STOP always, and unconditionally, halts the program. STOP also has the special feature of not closing any open files (which an untrapped error, or END, will). STOP will not trigger your error handler (if any) so you may want to do something like this in circumstances when it could otherwise leave something in an unstable state:

Code: Select all

      PROCcleanup : STOP
So I use the keyword RUM (which is not a keyword at all, of course) and that stops the program in its tracks
Don't do that, because by triggering a deliberate error you overwrite both ERR and ERL, the values of which can be invaluable for debugging.
Ivan
Posts: 127
Joined: Tue 07 May 2019, 16:47

Re: Trace and debug

Post by Ivan »

KenDown: I also use stops and have a lots of variables printed in an area, where it won't disturb the graphics too much.

Richard: Thanks I will try your suggestions.

I did use the Danish UNICOMAL for DOS in the eighties which also were produced by Acornsoft for the BBC Micro.

https://en.wikipedia.org/wiki/COMAL
TRACE.JPG
You do not have the required permissions to view the files attached to this post.
BBC Model B - 1984-1989. 6502 assembler, Unicomal 1988-1994, Some C and C++, Pascal 1990-1994. Bought a copy of BBC-BASIC 2007, but started to program at a daily basis 2019. C++ in 2021.
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Re: Trace and debug

Post by KenDown »

My programs are usually either full screen or take up a significant portion of the screen, so that the program listing is hidden or nearly hidden behind the program window. That is why a second monitor is so useful - though not, of course, essential.

I am aware that the beep means that there is no window with the input focus, but the problem is that sometimes clicking on the program window does not produce a cursor! I don't know whether it is because the program has been running under VDU 5 or because it has multiple windows or ... but whatever the reason, there is no cursor in the window and clicking on the window does not produce one. The only solution is to minimise and then restore the window.

Thanks for the information that STOP doesn't close files.

As my programs are not written with lines, I don't see that ERL is of any use - it just returns the value of zero! You are correct that ERR is overwritten but under the circumstances where I am using RUM I already know what the problem is, I'm just trying to find what has caused it!
RichardRussell

Re: Trace and debug

Post by RichardRussell »

Ivan wrote: Mon 02 Mar 2020, 13:49I did use the Danish UNICOMAL for DOS in the eighties which also were produced by Acornsoft for the BBC Micro.
BBC BASIC is quite flexible and you can achieve much the same thing as your COMAL example using a custom error handler (with a few tricks). Try running this code in BB4W or a 32-bit edition of BBCSDL (as it stands it's not reliable, for example it will fail if an error occurs when not in a procedure, but it could be worked up into a more functional 'advanced' error handler that could be put into a library):

Code: Select all

      HIMEM = HIMEM - 256 : REPEAT ON ERROR PROCerrorhandler : UNTIL TRUE
      HIMEM = HIMEM + 256

   10 DIM a(3), b(3)
   20 
   30 PROCtest1(1)
   40 PROCtest2(5)
   50 END
   60 
   70 DEF PROCtest1(num)
   80 a(num)=RND(5)
   90 ENDPROC
  100 
  110 DEF PROCtest2(num)
  120 b(num)=2+RND(3)
  130 ENDPROC

      DEF PROCerrorhandler
      DIM s%% LOCAL -1 : t%% = !s%% : s%% = HIMEM - 256
      REPEAT s%% -= 4 : UNTIL !s%% = t%% : t%% = s%%!4
      PRINT " Because of " REPORT$
      PRINT " the program stopped at"
      PROCprintline(PAGE + !408 - !340, r%%)
      PRINT " within"
      PROCprintline(r%%, s%%)
      PRINT " which was called at"
      PROCprintline(t%%, r%%)
      END

      DEF PROCprintline(l%%, RETURN r%%)
      LOCAL F%, p%%, q%% : p%% = PAGE
      REPEAT q%% = p%% : p%% += ?p%%
        IF p%%?3 = &DD r%% = p%%
      UNTIL ?p%% = 0 OR p%% > l%%
      F% = OPENOUT(@tmp$ + "ll.bbc.tmp")
      BPUT#F%,?q%% : BPUT#F%,q%%?1 : BPUT#F%,q%%?2
      PRINT #F%,$(q%%+3) : BPUT#F%,0 : CLOSE #F%
      OSCLI "list """ + @tmp$ + "ll.bbc.tmp"""
      ENDPROC
When this program is run this is what is printed:

Code: Select all

 Because of Bad subscript
 the program stopped at
  120 b(num)=2+RND(3)
 within
  110 DEF PROCtest2(num)
 which was called at
   40 PROCtest2(5)
RichardRussell

Re: Trace and debug

Post by RichardRussell »

KenDown wrote: Mon 02 Mar 2020, 21:01 My programs are usually either full screen or take up a significant portion of the screen
I rarely do that. The main reason is that there's no standardisation of screen shape or resolution, so running a program full screen typically makes it highly non-portable (unless you code it to adapt to the current screen resolution, but that's a real pain in BB4W). Another is that it's usually unnecessary: not many programs need that amount of 'real estate'.
the problem is that sometimes clicking on the program window does not produce a cursor!
I wouldn't expect that to happen in the case of an ordinary BASIC program, but if you call any Windows API functions (for example if you use any of the WINLIB libraries) then it's possible. It should be avoidable by ensuring that there's a 'catchall' error handler that activates a 'cleanup' routine which undoes the Windows-specific initialisation.
As my programs are not written with lines, I don't see that ERL is of any use
As this thread is about debugging, and since one of the most valuable debugging techniques is temporarily to add line numbers to your program, it is relevant. Almost invariably the first thing I do if a program of mine fails is that I renumber it, otherwise the default error report is useless (it only tells me what the error is, not where). Of course I get rid of the line numbers again when the errors have been cleared.
KenDown
Posts: 327
Joined: Wed 04 Apr 2018, 06:36

Re: Trace and debug

Post by KenDown »

My most important program (from my point of view) is an improved PowerPoint, so full-screen is more or less imperative! However even with those that don't need full screen, many if not most take up a significant portion of the screen and would largely or partially obscure the program listing. A second monitor just make life so much easier in all sorts of ways.

I would be very grateful indeed if someone could come up with the sort of "clean-up" routine you envisage. Even a pointer or two to what such a routine should incorporate would be helpful.

Yes, I have added line numbers to my programs on occasion, but generally I find that having the listing visible is all I need. The facility you devised of having the error not only highlighted but the view jumps to the error line is superb.

The main time when I find line numbers useful is when an error crops up in a compiled program that was not evidence before it was compiled. A compiled program will, if the error handler is set up correctly, report the error and the line number and you then look up the program listing.
Ivan
Posts: 127
Joined: Tue 07 May 2019, 16:47

Re: Trace and debug

Post by Ivan »

Richard: Fantastic!

"(as it stands it's not reliable, for example it will fail if an error occurs when not in a procedure, but it could be worked up into a more functional 'advanced' error handler that could be put into a library)"

1. "library" could that be named/called as a "trace" command or?

2. I have a mildly form of dyslexia and miss that the old Comal syntax checked a program line each time I pressed enter so I have stops of that reason...

3. Richard: Did you consider a single step trace and a watch window with selected variables - I have attached a suggestion with trace marks?

4. Directives: Maybe an on/off for declared variables, procedures and functions?

5. I find program a program list easier to read with procedure indention...

I apologise if I have suggested something that already is a feature.

single step trace and selected variables.jpg
You do not have the required permissions to view the files attached to this post.
BBC Model B - 1984-1989. 6502 assembler, Unicomal 1988-1994, Some C and C++, Pascal 1990-1994. Bought a copy of BBC-BASIC 2007, but started to program at a daily basis 2019. C++ in 2021.