Bug? More than 10 'select case' in the code

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
Please see this thread: https://www.b4x.com/android/forum/threads/select-case-in-b4r.106120/
Failures if more that 10 select cases in the code
It is not a bug with the compiler. I just made as simple 20-level test inside a for/next loop and it worked correctly. It must be something you're doing in your case statements.

I would suggest looking at each case and making sure that multiple case conditions are not true at the same time. The main difference between elseif/select is that select will process multiple true levels unless you add an "Exit" at the end of every block whereas an elseif will not.
 

RJB

Active Member
Licensed User
Longtime User
I'm not sure how you have tested it within a for/next loop, could you show the code? The problem occurs where there are over ten separate select cases.
I've never come across a select case that will process more than one case at a time, are you thinking of C or Java?
I've tried:
B4X:
Select Case 1
 Case 1
  Log("1st case 1")
 Case 1
  Log("2nd case 1")
 Case 1
  Log("3rd case 1")
End Select
and it logs only "1st case 1" as I would expect.
 

RJB

Active Member
Licensed User
Longtime User
Hi Klaus, it was just to prove how the case statement works. Jeffrey Cameron, in #3 above, seemed to be saying that all three 'cases' would be processed if there was no 'exit' at the end of each 'block'.
Both 'Select something' and 'Select Case something' work. Will using 'Select Case something' cause any problems?
Thanks
 

klaus

Expert
Licensed User
Longtime User
Will using 'Select Case something' cause any problems?
No, it works, didn't know it.
But anyway, in your example you test Case 1 and then test three times the same Case 1, I don't understans !???
Just saw that mcqueccu was faster.
 

Star-Dust

Expert
Licensed User
Longtime User
I've tried:
B4X:
Select Case 1
Case 1
  Log("1st case 1")
Case 1
  Log("2nd case 1")
Case 1
  Log("3rd case 1")
End Select
and it logs only "1st case 1" as I would expect.
????Very funny
 

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
could you show the code?
Very simple, just a for/next loop with 20 cases:
B4X:
Dim piIndex As Int
    Log("Start of 20 loop")
    For piIndex = 1 To 20
        Select Case piIndex
            Case 1
                Log("Case is 1")
            Case 2
                Log("Case is 2")
            Case 3
                Log("Case is 3")
            Case 4
                Log("Case is 4")
            Case 5
                Log("Case is 5")
            Case 6
                Log("Case is 6")
            Case 7
                Log("Case is 7")
            Case 8
                Log("Case is 8")
            Case 9
                Log("Case is 9")
            Case 10
                Log("Case is 10")
            Case 11
                Log("Case is 11")
            Case 12
                Log("Case is 12")
            Case 13
                Log("Case is 13")
            Case 14
                Log("Case is 14")
            Case 15
                Log("Case is 15")
            Case 16
                Log("Case is 16")
            Case 17
                Log("Case is 17")
            Case 18
                Log("Case is 18")
            Case 19
                Log("Case is 19")
            Case 20
                Log("Case is 20")
        End Select
    Next

Output is exactly as you would expect on my log, 20 individual lines.
 

RJB

Active Member
Licensed User
Longtime User
The point is that in #3 it was stated that each 'case' had to have an 'exit' and if not a duplicate (IN ERROR) 'case' (i.e. case 1, in the EXAMPLE TO PROVE THE POINT) would cause problems. That's not the case (pun not intended) if there is a duplicate case then only the first one is actioned. Of course no one would use the EXAMPLE that I gave. It was to prove the point.

Jeffrey I see the misunderstanding, it's not that there are 20 cases within a select or that one select is called 20 times. It is that there are more than ten individual 'selects' in the code. i.e.
B4X:
sub1
 dim index1 as int = 1

select index
  case 1
  'do something
  case 2
  'do something
  case 3
   'do something
 end select
end sub

sub2
 dim index2 as int = 2

 select index2
   Case 1
    'do something
   Case 2
    'do something
   Case 3
    'do something
 end select
end sub

'repeated to a total of eleven times will cause failures somewhere, maybe not in one of these subs

'if there are 10 or less 'selects' then it will be OK
 
Last edited:

RJB

Active Member
Licensed User
Longtime User
Regarding the original problem, this code cause a failure in another sub:
B4X:
Private Sub GetFontByte(Number As Int, Index As UInt) As Byte
 Select Case Number
   Case 0
    Return RunNative("getAdz1", Index)
   Case 1
    Return RunNative("getAdz2", Index)
   Case 2
    Return RunNative("getAdz3", Index)
   Case Else
    Return RunNative("getAdz1", Index)
  End Select
End Sub

whereas replacing it with this code and hence reducing the total number of 'selects' in the whole programme to 10 solved the problem in the other sub:
B4X:
Private Sub GetFontByte(Number As Int, Index As UInt) As Byte
 If Number = 0 Then
   Return RunNative("getAdz1", Index)
 else if Number = 1 Then
   Return RunNative("getAdz2", Index)
 else if Number = 2 Then
   Return RunNative("getAdz3", Index)
 Else
   Return RunNative("getAdz1", Index)
 End If
End Sub
 

RJB

Active Member
Licensed User
Longtime User
I'm beginning to think this is some kind of memory or stack problem. I've experimented further.
Using the following code (WHICH IS ONLY FOR TESTING AND IS NOT INTENDED TO ACHIEVE ANYTHING USEFUL!) with the subs commented out as shown there is no problem.
B4X:
#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 1500
#End Region
Sub Process_Globals
'These global variables will be declared once when the application starts.
'Public variables can be accessed from all modules.
Public Serial1 As Serial
End Sub
Private Sub AppStart
Serial1.Initialize(115200)
Log("AppStart")

' Sub1
' sub2
' Sub3
' sub4
' Sub5
' sub6
' Sub7
' sub8
' Sub9
' sub10
' Sub11
' sub12
Dim x() As Byte = "abcd"
Anothersub(1, 2, 3, x)
Log("RAM3: ", AvailableRAM)
Log("Stack3: ", StackBufferUsage)
End Sub
Sub Anothersub(x As Int, y As Int, z As Int, Text() As Byte)
Log("RAM1: ", AvailableRAM)
Log("Stack1: ", StackBufferUsage)
Log("Another sub")
Log(Text)
Log("RAM2: ", AvailableRAM)
Log("Stack2: ", StackBufferUsage)
End Sub
'Sub Sub1
' Log("Sub 1")
' Dim index1 As Int = 1
'
'Select index1
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'Sub sub2
' Log("Sub 2")
' Dim index2 As Int = 2
'
' Select index2
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'
'Sub Sub3
' Log("Sub 3")
' Dim index1 As Int = 1
'
'Select index1
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'Sub sub4
' Log("Sub 4")
' Dim index2 As Int = 2
'
' Select index2
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'
'Sub Sub5
' Log("Sub 5")
' Dim index1 As Int = 1
'
'Select index1
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'
'Sub sub6
' Log("Sub 6")
' Dim index2 As Int = 2
'
' Select index2
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'
'Sub Sub7
' Log("Sub7")
' Dim index1 As Int = 1
'
'Select index1
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'Sub sub8
' Log("Sub8")
' Dim index2 As Int = 2
'
' Select index2
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'Sub Sub9
' Log("Sub9")
' Dim index1 As Int = 1
'
'Select index1
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'Sub sub10
' Log("Sub10")
' Dim index2 As Int = 2
'
' Select index2
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'Sub Sub11
' Log("Sub11")
' Dim index1 As Int = 1
'
' Select index1
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
'
'Sub sub12
' Log("Sub12")
' Dim index2 As Int = 2
'
' Select index2
' Case 1
' 'do something
' Case 2
' 'do something
' Case 3
' 'do something
' End Select
'End Sub
However if I increase the stack buffer to 1600 (AGAIN ONLY TO SHOW THE PROBLEM) to use more memory then the log shows:
B4X:
.......

Sketch uses 6168 bytes (19%) of program storage space. Maximum is 32256 bytes.
Global variables use 281 bytes (13%) of dynamic memory, leaving 1767 bytes for local variables. Maximum is 2048 bytes.
Uploading...
********************* PROGRAM STARTING ****************
AppStart
2986344448020480-1023035899095813632-805306368474624-3019898880071680036074291201125268492608358439375939379300.00000.0000
Stack1: 4
Another sub
RAM2: 1719
Stack2: 4
RAM3: 1714
Stack3: 4

If I remove the log("Stack....) and log("RAM....) lines then I get:
B4X:
.........
Sketch uses 5452 bytes (16%) of program storage space. Maximum is 32256 bytes.
Global variables use 281 bytes (13%) of dynamic memory, leaving 1767 bytes for local variables. Maximum is 2048 bytes.
Uploading...
********************* PROGRAM STARTING ****************
AppStart
An

and nothing else.

This is running on a UNO with a display and SD card attached.
 

RJB

Active Member
Licensed User
Longtime User
Just tried it with a different UNO with nothing connected to it: same result but different random characters in the log:
B4X:
AppStart
ovf020480212802550071680034853393734047007694��x�V��V��Z���(e^)�u �a�T��_u�ʑ�^>�>o�w���mM"28366���/�;R<����~"�u���r�x7޺���5�v�x6g?�z��iu������>KS�Qz�x�����k��x�V��V��Z���(e^)�u �a�T��_u�ʑ�^>�>o�w���mM�
 

OliverA

Expert
Licensed User
Longtime User

RJB

Active Member
Licensed User
Longtime User
From the additional testing I did I think that may be right.
But with so little code and data and the log showing 16% program and 13% dynamic memory used it seems strange. Also the Available RAM and StackBufferUsage logs don't seem to show a problem. What you can't check (as far as I know) is the normal stack, as opposed to the Stack Buffer, so maybe that's the problem?
 

RJB

Active Member
Licensed User
Longtime User
The other thing that might help point out what's going on is that in the original code replacing one of the' select, case, end select' s with a 'if, else if, end if' made the code work.
 
Top