I have been getting an exception which I eventually worked out was due to a stack overflow when I had implemented an EEPROM blank check type of sub. The sub is shown here:
B4X:
Private Sub Check_EEprom(start As UInt, finish As UInt) As Boolean
Log("Start checking ...")
' Check if any location not cleared to zero
Dim success As Boolean = True
Dim n As UInt
For n=start To finish
Log(n, " ", EE.ReadBytes(n,1)(0))
Log("stack: ", StackBufferUsage)
If EE.ReadBytes(n,1)(0) <> 0 Then success = False
Next
Log("EEPROM check result: ",success)
Return success
End Sub
As you can see I'm logging the stack buffer usage in the loop and from the logs I can see this increasing by 24 every step until n=168 when the exception is thrown up (and causes a reset of an ESP8266 module in my case). I think I understand that EE.ReadBytes gets a new array each time so I guess that these are just stacking up (though why 24 bytes each time not sure - 12 bytes for each EE.Readbyte). Any views on this and perhaps suggestions for better ways to achieve it? I do know that I can avoid the continual stacking by doing something like x=EE.ReadBytes(n,1)(0) in a second sub which I then call from the above, but this seems like a crude work around arising from my poor underlying understanding.
1. You can increase #StackBufferSize.
2. The log in line #7 will also consume memory as you are implicitly creating an array there.
3.
Moving the loop code to a separate sub will allow the memory to be released after each iteration:
B4X:
Private Sub Check_EEprom(start As UInt, finish As UInt) As Boolean
Log("Start checking ...")
' Check if any location not cleared to zero
Dim success As Boolean = True
Dim n As UInt
For n=start To finish
If ReadSingleByte(n) Then success = False
Next
Log("EEPROM check result: ",success)
Return success
End Sub
Private Sub ReadSingleByte(n As UInt) As Boolean
Log(n, " ", EE.ReadBytes(n,1)(0))
Log("stack: ", StackBufferUsage)
Return EE.ReadBytes(n,1)(0) <> 0
End Sub
I suppose I was trying to understand what was going on. I know I could have increased stack size but felt that would be just covering up my lack of understanding and does not really resolve the intrinsic problem in the general case. From the tutorials I did have a vague understanding that if I put the EE.readbytes operation in another sub then likely that the memory allocation would be cleared upon return from that sub, but my first attempt to do this didn't actually work. For example say I changed my original code to:
B4X:
Private Sub Check_EEprom(start As UInt, finish As UInt) As Boolean
Log("Start checking ...")
' Check if any location not cleared to zero
Dim success As Boolean = True
Dim n As UInt
For n=start To finish
Log(n, " ", ReadSingleByte(n))
Log("stack: ", StackBufferUsage)
If ReadSingleByte2(n) <> 0 Then success = False
Next
Log("EEPROM check result: ",success)
Return success
End Sub
Private Sub ReadSingleByte(n As UInt) As Byte
Return EE.ReadBytes(n,1)(0)
End Sub
I found that this resulted in the same stack overflow issue. But if I changed the second sub to:
B4X:
Private Sub ReadSingleByte(n As UInt) As Byte
Dim sb As Byte
sb = EE.ReadBytes(n,1)(0)
Return sb
End Sub
Then in the latter case no stack overflow. So I did have a solution, but couldn't really understand why the second method did clear the memory allocation for the array whereas the first didn't. Your suggestion is of course even more code efficient
Anyhow the problem is resolved. Like I say, more curiosity to see if there was some other way that I had missed to read the bytes efficiently without resorting to a second sub. Also perhaps a point of caution to others.
Ah, I see. So casting this into my original code just for philosophical clarity, I'm guessing this might be the way:
B4X:
Private Sub Check_EEprom(start As UInt, finish As UInt) As Boolean
Log("Start checking ...")
' Check if any location not cleared to zero
Dim success As Boolean = True
Dim n As UInt
Dim sb(1) As Byte
For n=start To finish
EE.ReadBytes2(n,1,sb)
Log(n, " ", sb(0))
Log("stack: ", StackBufferUsage)
If sb(0) <> 0 Then success = False
Next
Log("EEPROM check result: ",success)
Return success
End Sub
So though still involving an intermediate variable (philosophic), avoids the call to another sub. This feels neater to me. Thanks for that insight.