Skip to content

Code Tip: Be Careful With Loops

Every once in a while we get a question or post like this one that wonders why a loop might turn into an infinite loop or why it doesn’t behave as expected and stop when the loop reaches the limit.

In this case the specific FOR NEXT loop in question is :

For X As UInt8 = 0 To 255 
  Dim strAnything As String = "Hello World" 
Next

If you run this code you’ll find that it runs forever. You’ve accidentally created an infinite loop.

How did this come to be this way? There are two things involved. One is what range of values a Uint8 can actually store. And the second is the actual code generated for the for loop itself. When these two combine the stopping conditions will never occur.

Uint8 values can hold a range of values like any integer. They are all positive. And the range is from 0 – 255.

So a Uint8 will NEVER hold a value > 255 or < 0.

Combine this with the fact that a FOR loop is generated using roughly this underlying code

Dim loopCounter As UInt8
Dim loopLimit As Integer = 255
Dim loopBase As Integer = 254
Dim loopStep As Integer = 1

loopCounter = loopBase

loopTop:
  If loopCounter > loopLimit Then
    GoTo loopEnd
  End If
  
  // loop body code would be here
  // its been elided to focus on the actual loop mechanics
  //    dim strAnything as string = "Hello World" 
  // 
  loopCounter = loopCounter + loopStep // NOTE THIS CAN CAUSE OVERFLOW !

  GoTo LoopTop

loopEnd:

This is NOT the actual code used. It is just a Xojo version of the actual underlying LLVM IR code that gets generated.

Hopefully this explains the confusion. Since a Uint8 cannot hold a value greater than 255, you will find that when loopCounter IS already 255 and the increment, or loopStep in this example, is added to the existing value the loopCounter goes NOT from 255 to 256 but back to 0. It wraps around. This isn’t a bug.

The addition of the loopStep value causes the Uint8 to overflow since the value 256, in binary, requires 9 bits, not 8 but the Uint8 can only hold 8 bits. And so when you add it the 8 bits the value can hold are all 0 and the loop counter resets to 0.

And this behavior is not specifically a Xojo thing, most programming languages do this. In fact, there are some very well know encryption algorithms, like BlowFish, that rely on this  .

In the specific sample code that prompted this post, a loop counter that is an Integer or Uint16 is needed because they can hold values that exceed the loops upper bound.

Loops that count down have a similar problem. but counting down and underflowing instead of overflowing.

The moral of the story is to stick to using the general Integer data type unless you have a specific need for a size-specific Integer type.