I am writing a quick Linux desktop app and seemingly strange things are happening with For…Next loops.
For example, the following code is supposed to detect how many times “1” occurs in a string:
dim intTestCount as integer
For intIndex as integer = 1 to 256
if strData.Mid(intIndex, 1) = "1" then
intTestCount = intTestCount + 1
intTestCount then equals 135 which is impossible since (a) the loop can only increment
intTestCount to a max of 256 and (b) the
strData.len = 256 !
And another thing. If intIndex in a loop (not the one above) is defined as uint8, with the range being from 0 to 255, the loop overflows with a n exception when it reaches 255. That is to say there seems not to be the full 256 numbers in the range!
I usually use Do loops with manual counters not For Next loops because very explicit code is cheaper to maintain in the long run. However on this occasion I wanted the code to be brief but have spent a lot of time wrestling with problems with the For Next control structure itself.
I will go back to Do loops but I want to find out if it is just my dev environment or does anyone else ever see this in the Linux IDE ?
What are the contents of strData?
Anthony, it’s binary string of characters produced from the Bin function: "00100110 etc
However there can never be more increments in the counter going up by +1 than there are passes in the loop, no matter what the data was in the string.
OK, then I’m not seeing the issue unless there’s a typo here…
completely normal behavior for me too.
OK it’s something with my system then. Strange thing is the same kind of code seems to work a couple of dozen lines above in the same routine. But not with the overflow issue.
Eric, 135 is less than 256, so it is possible to get 135 out of a max 256.
Can you post the exact loop that get the overflow issue?
Yes I saw that Alberto - it’s 4:17AM here so sorry about that. But the overflow issue seems real.
For X as uint8 = 0 to 255
dim strAnything as string = "Hello World"
Eric, you don’t have to be sorry about it, it happens.
I tested the For Next on macOS and the test run just freeze. If I change to 254 then there is no problem.
I did a test with uint16 and 0 to 65535 and got the same.
I don’t know much of how Xojo works, do you think that the for next go to that value (255 or 65535) and execute the code inside of it and the problem is when it gets to ‘Next’ that it tries to go to 256 (or 65536) and those values are not valid? so it goes to 0 again (thank you Andre).
ETA: just used this code and it works, it looks like the last Next is the problem:
For X As UInt8 = 0 To 255
Dim strAnything As String = "Hello World"
if x = 255 then exit // this way Next will not try to increment X beyond Uint8 limit
ETA2: Thank you Andre, good to know.
The problem is that uint8 can only hold values upto 255, if the uint8 variable = 255 and you add 1 the value becomes 0 again and the next will start the loop all over again.
In this case you should use a variable with at least 16bits to prevent the problem.
The real problem is that Xojo doesn’t support overflow for integer variables.
In fact you created an endless loop.
The moral: if you use an integer as a loopcounter be sure to use the type that can handle the whole range of the loop +1.
Agreed. But there are 256 numbers in a uint8 not 255 so it’s counter-intuitive that
For x as uint8 = 0 to 255 should be a problem. I do this type of thing often with Do loops after all using the full range of the variable.
However I am comforted by the fact I haven’t gone crazy and that others see it too!
Right, but the last next will try to increase the value of x but because x is limited to a max of 255 it will go round to zero again.
In a do loop the check for the value of x is at the end of the loop and as soon the var x is 255 it will not be increased anymore and the loop will end. In that case x will never be asked to take a value higher than that 255.
OK but I don’t recall having this problem with
For..Next in my VB days nor with Open/Libre Office. It’s counter-intuitive which is why I’m heading back to Do loops.
In my real-world situation the debugger caught the exception but in my example code the test run went into hyperspace like Alberto’s mac. That is not a good look since
For...Next isn’t exactly new, but at least the platforms are consistent!
In most programs in VB i have seen the variables were dimmed as integer and that integer has a much bigger range and would never show a problem with ranges from 0 to 255. I have never done anything with Open Office, so i cann’t comment on that.
It could be that do loops are a little bit less efficient because you need extra code to increment the loopcounter yourself, but with this smal range it will hardly be measurable. So there is nothing against using them.
I tested this on Windows and it shows exactly the same behaviour.
At least you now know where the problem is and you can be sure you are absolutely not getting crazy.
Thanks for the link Jason. Although somewhat unintentional, I’m glad the uint data types were included in mainstream Xojo. For me, they are important for allowing interoperability between bitwise, mathematical and string bin() and val(&b 32bit) functions. Otherwise bitwise operations would be much harder to use with signed integers. However in this case I was using uint to catch overflow errors which would not stop execution and could otherwise go unnoticed leading to difficulties in debugging, since signed integers are capable of greater and/or signed negative ranges that my application should not allow or have to deal with. Therefore I think
For...Next deserves access to the full range of unsigned integers expressly dimensioned by programmers for counting purposes., so that when dealing with a byte one can use an uint8 loop for example. Until that day comes I’ll stick with
Do...Loop with counters.
uint8 can hold integers from 0 to 255, which is 256 distinct values.
It’s not big enough to hold a value of 256 (9 bits).
Start with 0 as the 1st value, counting by 1, the 256th ‘value’ will be 255.
For...Next adds 1 to the counter at the bottom of the loop,
THEN it checks if the counter is greater than the limit.
A UInt8 counter will fail (or reset to 0) when it tries to increment to 256.
[quote]A UInt8 counter will fail (or reset to 0) when it tries to increment to 256.[/quote]’’
I would like this to be so but it overflows before incrementing to 255. Please run the example code above to verify this with uint8 counters. Anyway,
Do...Loop has no such issue if incrementing at the bottom and one’s code is clearer too.
Running in the debugger, breakpoint on the dim:
For X as uint8 = 0 to 255
dim strAnything as string = "Hello World"
On windows X rolls over to 0 after 255, endless loop.