Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bug: String Slicing (*solved*)
#1
I think string slicing still has bugs in it. Not quite sure why this fails, but it produces code that runs briefly and crashes, running in Spectaculator:
(fails with or without the DIM statements, but crashes differently in each case)
Code:
DIM A$,p$ as string
DIM start,fin as integer

10 LET a$="This is a very long scrolly string that I am going to print"
20 LET start=1
30 LET fin=32
40 LET p$=a$(start TO fin)
50 LET start=start+1
60 LET fin=fin+1
70 IF fin>LEN a$ THEN LET fin=1  : END IF
80 IF start>LEN a$ THEN LET start=1 : END IF
90 PRINT AT 0,0;p$
100 IF start<fin THEN GO TO 40 : END IF
110 LET p$=a$(start TO )+a$( TO fin)
120 GO TO 50


Correcting the 1 to Zero (Since in compiled code the strings begin slicing at zero) has no effect other than change the way it crashes:

Code:
DIM A$,p$ as string
DIM start,fin as integer

10 LET a$="This is a very long scrolly string that I am going to print"
20 LET start=0
30 LET fin=31
40 LET p$=a$(start TO fin)
50 LET start=start+1
60 LET fin=fin+1
70 IF fin>LEN a$ THEN LET fin=0  : END IF
80 IF start>LEN a$ THEN LET start=0 : END IF
90 PRINT AT 0,0;p$
100 IF start<fin THEN GO TO 40 : END IF
110 LET p$=a$(start TO )+a$( TO fin)
120 GO TO 50
Reply
#2
This is a bit odd... Confusedhock:

The 1st time the program runs ok (at less in the new version 1.2.1, which in fact changes the heap memory scheme).

Note:
Quote:In current releases, once you return to basic, the initialization routines are corrupted, so you can't enter the program again using RANDOMIZE USR. You have to reload it. This is because I use a scheme to save memory that once initialized, uses that memory for variables (so it gets corrupted).
The new initialization scheme works in a different way, so you can re-run the program (e.g. by using RANDOMIZE USR 32768) as much as you want.

Back to the topic: I compiled with v.1.2.1. I don't see any crash. Reruning the program with RANDOMIZE USR effectively works too! So test the release 1.2.1 (I'll put it in a few minutes) and tell me if it works for you.

The Problem:
String variables a$ and p$ keep the previous execution values. So when you do p$ = a$(...), the previous value of p$ is still in memory, pointing to a heap location that gets corrupted, because on each runs the heap is initialized and then the program tries to "release" the previous value of p$ (which does not exist anymore). Hmmmm. If this is too technical, forget it... Just tried to explain you the reason.

Now exiting to BASIC does preserve everything, so initializing the program works, but it preserves all the variables. :!:
Remember this is like in C. Declaring an initialized variable does not mean it is assigned on each execution:

Code:
// In C
int a = 1; /* this just means to reserve a memory location containing 01 00 00 00 */

// In ZX BASIC
DIM a as Integer = 1 : REM The same

DIM b
LET b = 0  : REM This ENSURES b is assigned 0 on each execution
So, basically, if you expect your program to be run more than once, use LET. Otherwise, just initialize the variable with DIM (faster and saves some bytes).
Reply
#3
I only ever ran it once, because it crashed and I had to reset the emulator after each run!
Incidentally, how did you run it multiple times? It should never return to basic - just scroll forever.

I recompiled with 1.2.1 and nope: still crashes.

I was using version 2 (slicing from 0) - copy and pasted exactly as I'd listed it.

Procedure:

compile test.bas to test.bin, using default org of 32768. No command line switches:

zxb test.bas

Start up Spectaculator
CLEAR 32767
load binary file into 32768
LET l=USR 32768

It cycles round the scroller about 4 times and then writes all over the screen and locks the machine.

I haven't tested the new code with BASin at this time, but on 1.2.0 yesterday it behaved exactly the same on BASIN as it did on Spectaculator, so I don't think it's an emulator issue.

Edit: Crashes identically when loaded into BASin and run, using 1.2.1.
Edit: Seems to do the behave identically same in O3 mode. I can't work out how Boriel got it to run.

Boriel: What are you testing compiled code on?
Reply
#4
britlion Wrote:I only ever ran it once, because it crashed and I had to reset the emulator after each run!
Incidentally, how did you run it multiple times? It should never return to basic - just scroll forever.

I recompiled with 1.2.1 and nope: still crashes.

I was using version 2 (slicing from 0) - copy and pasted exactly as I'd listed it.

Procedure:

compile test.bas to test.bin, using default org of 32768. No command line switches:

zxb test.bas

Start up Spectaculator
CLEAR 32767
load binary file into 32768
LET l=USR 32768

It cycles round the scroller about 4 times and then writes all over the screen and locks the machine.

I haven't tested the new code with BASin at this time, but on 1.2.0 yesterday it behaved exactly the same on BASIN as it did on Spectaculator, so I don't think it's an emulator issue.

Edit: Crashes identically when loaded into BASin and run, using 1.2.1.
Edit: Seems to do the behave identically same in O3 mode. I can't work out how Boriel got it to run.

Boriel: What are you testing compiled code on?
I produce .tzx files to be directly loaded (e.g. EmuzWin, Fuse, Xspect/spectemu).
The TZX or TAP already produce the basic loader and auto-executes when loaded with LOAD "".

Use the following command line:
Code:
zxb.exe --autorun --BASIC --txz test.bas
This will produce a test.tzx file to be directly opened by your emulator with LOAD "". A BASIC program comes first, later the code (Bytes: header).
I'm not sure how other emulators interpret the .bin files. BIN files are just the compiled bytes with no header info.

This should work for you. Tell me if not.

UPDATE: I'm going to test what you do with BASIN, etc.
UPDATE2: Tested on BASIN using .tzx -> Works OK
UPDATE3: Tested on Spectaculator (Demo mode) using .bin WORKS ok :?: :?:
Reply
#5
Erm. Um. :?:

Okay. Hopefully you can grab this file: <!-- m --><a class="postlink" href="http://britlion.googlepages.com/test.tzx">http://britlion.googlepages.com/test.tzx</a><!-- m -->

Is this working on your emulator? Because in Spectaculator 7.00 it loads, scrolls for a few seconds, and crashes!
Reply
#6
britlion Wrote:Erm. Um. :?:

Okay. Hopefully you can grab this file: <!-- m --><a class="postlink" href="http://britlion.googlepages.com/test.tzx">http://britlion.googlepages.com/test.tzx</a><!-- m -->

Is this working on your emulator? Because in Spectaculator 7.00 it loads, scrolls for a few seconds, and crashes!

This file effectively crashes. However, are you sure this file is the compilation of the above Source Code? It seems it is not.
The way it crashed might suggest a Stack Overflow. Are you using GOSUB or function calls in that code?

Update: Confusedhock: Believe it or not, I have download again the 2nd example, compiled it and now it CRASH :?: :?:
So I now have something to test. Wink

Update2: Fixed. The problem are lines 70 & 80. They should read:
Code:
70 IF fin>=LEN a$ THEN LET fin=0  : END IF
80 IF start>=LEN a$ THEN LET start=0 : END IF
This is because when fin == LEN a$, a$(fin) is beyond end of a$ (should be fin-1). Anyway, the program should not crash: I put some overflow checking to avoid this.

I will put some more checking, but since this will slowdown array/string accesses. I think It could be a good idea to put some compiler option to enable/disable array/strings boundary checks. Once the program is debugged, you can recompile disabling it.

Another fix could be to enable a flag like:
Code:
zxb --string-base=1
The same as "array-base" flag. So, for maximum compatibility:
Code:
zxb --string-base=1 --array-base=1
or better
Code:
zxb --sinclair
What do you think?

Note: --sinclair already exists, but does not change string-base
Reply
#7
Argh.

Yes, of course - the number returned by LEN becomes greater than the index of the last character.

Ack!

*bangs head*

You know, in something like Java or C I don't even blink on that concept. I think the problem here is I'm working with Sinclair Basic programs and converting them.

Time to adjust my compile.bat to have --sinclair as a default, and leave it that way.
Reply
#8
Quote:I will put some more checking, but since this will slowdown array/string accesses, I think It could be a good idea to put some compiler option to enable/disable array/strings boundary checks. Once the program is debugged, you can recompile disabling it.

I really like this idea for testing. If it throws an error at that point, it's very useful for debugging - but correct code shouldn't do that. I like the idea of a
-nodebug option to make for faster code, at the user's risk :-)

(perhaps this could be part of the optimization system, so -O3 does this?)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)