B4R Question For-Next error after 16 cycle in JoinStrings

petr4ppc

Active Member
Licensed User
Dear friend please for advice:

I have code:
B4X:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
For i = 0 To buffer.Length-1
Dim cbtx(1) As Byte
byteconvert.ArrayCopy2(buffer,i,cbtx,0,1)
receivebyte = byteconvert.StringFromBytes(cbtx)
allbytesasstringarehere= JoinStrings(Array As String(allbytesasstringarehere, receivebyte)) 
next
But I get this error after i=16 ("z") in word "xyz"

Exception (3):
epc1=0x4020e161 epc2=0x00000000 epc3=0x00000000 excvaddr=0x400293c1 depc=0x00000000
>>>stack>>>
ctx: sys
sp: 3ffffd00 end: 3fffffb0 offset: 01a0
3ffffea0: 40000f3d 00000023 00000000 3ffe8b08
3ffffeb0: 3ffe8b08 4022079c 00000010 4020e258
3ffffec0: 00000000 4021924c 00003637 4022079c
3ffffed0: 00000000 4bc6a7f0 40100564 000035eb
3ffffee0: 00000000 00000000 4bc6a7f0 40217b90
3ffffef0: 003e58da 00000013 00003637 40217bcc
3fffff00: 4021924c 000035eb 3fff2114 402191f1
3fffff10: 4021924c 000035eb 3fff1dac 4021927f
3fffff20: 3ffe8b08 00d25e16 60000600 40217bf6
3fffff30: 00d2a1bc 3ffee6b0 3fff1dac 402193f4
3fffff40: 4024d60c 3ffee688 3ffee6b0 60000600
3fffff50: 00d2a1bc 3ffee6b0 3ffee688 4024d619
3fffff60: 4024d65e 3fffdab0 00000000 3fffdcb0
3fffff70: 3ffee6d0 3fffdad0 3fff1a08 4020c8ef
3fffff80: 40000f49 40000f49 3fffdab0 40000f49
3fffff90: 40000e19 40001878 00000002 3fff19d0
3fffffa0: 3fffff10 aa55aa55 00000039 40104a54
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
Please what can I do?
Everytime only 16 cycles of FOR-NEXT is processed and then I get this error.
Thank you
p4ppc
 

petr4ppc

Active Member
Licensed User
i am working on int and I found, that if I
set
B4X:
#StackBufferSize: 2600
was
B4X:
#StackBufferSize: 600
then I can work with more longer string.

How I must set STACKBUFFERSIZE if I want work with array of 360 letter in the string? Please?
Thank you
p4ppc
 

emexes

Well-Known Member
Licensed User
Spewin! I got most of the way through a reply whilst waiting at airport to collect son, but apparently got distracted and never clicked Post Reply button.

upload_2019-10-5_23-13-13.png
 

petr4ppc

Active Member
Licensed User
Emexes,

thank you very much for your answer and advice. I have tried to put FOR NEXT to new SUB routine,
but the stackbuffer have the same value.

Thanks for tip
B4X:
Log("stackbuffer:",StackBufferUsage)
It is very useful.

I understand it right that the solution how to secure function "join string" via FOR NEXT is with new sub routine? Because of memory?
I have realy the same Stackvalue in both variant.
Best regards
p4ppc
 
Last edited:

emexes

Well-Known Member
Licensed User
What are you actually trying to achieve with this code:
B4X:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
For i = 0 To buffer.Length-1
    Dim cbtx(1) As Byte
    byteconvert.ArrayCopy2(buffer,i,cbtx,0,1)    'get next byte from input
    receivebyte = byteconvert.StringFromBytes(cbtx)    'convert byte/character to string
    allbytesasstringarehere= JoinStrings(Array As String(allbytesasstringarehere, receivebyte))    'add to output string
next
It looks like you are chopping up the input string into individual characters that are then being joined back into a single output string.

Usually this would just be done by a single string/array copy that does the whole string all at once.

Is this purely to demonstrate the error?

There are far more efficient ways to process a string character-by-character, usually involving Dimming the output buffer to the final size, rather than having a whole heap of differently-sized intermediate strings.

So, just in case the original question was missed: what string operation(s) are you actually needing to do?
 

emexes

Well-Known Member
Licensed User
what string operation(s) are you actually needing to do?
as in, why not use ByteConverter .StringFromBytes to do the whole string at once?
B4X:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
Dim allbytesasstringarehere As String = byteconvert.StringFromBytes(buffer)
 

petr4ppc

Active Member
Licensed User
EMEXES - EREL

Thank you very much for yours answer

- I am receiving standard serial data from AVR
- this bytes are reading in ESP - each byte
- Each byte is then compared with values in EEPROM and then I put the right values to the string

But as I wrote - I recognized that if the string is too long, ESP is restarted. It depend on #StackBufferSize...

I will try what Erel wrote:
You need to keep the For loop in the original sub and move the inner code to a different sub. This will allow the stack memory to be released after each iteration.
And thank you for your tip Emexes:
Dim buffer() As Byte = "hallo how are xyz I am fine and you?"
Dim allbytesasstringarehere As String = byteconvert.StringFromBytes(buffer)
Best regards
p4ppc
 

petr4ppc

Active Member
Licensed User
Excuse me,

- If I have the string with right data I am sending them :

1) via serial back to AVR (this is most important)
and
2) I am working now on B4J app for second possibility = sending data via UDP. ESP to B4J

Best regards
p4ppc
 

emexes

Well-Known Member
Licensed User
I will try this solution.
Super!

Part of me says: you're on the right track, I should leave you in peace.

Another part says: what was all that byte-string-shuffling about? makes me worry that whatever you are doing, you might be doing it the hard way.

You haven't told us what you are doing with this string so it is impossible to say more.
+1
 

petr4ppc

Active Member
Licensed User
Dear friends,

I am trying:
B4X:
Private Sub AppStart
    Serial1.Initialize(115200)
    Log(" ") : Log("AppStart")
    Queue.AddBytes("h")
    Queue.AddBytes("a")
    Queue.AddBytes("l")
    Queue.AddBytes("l")
    Queue.AddBytes("o")
    Queue.RemoveFirst
    Queue.AddBytes("h")
    Queue.AddBytes("o")
    Queue.AddBytes("w")
    Queue.AddBytes("a")
    Queue.AddBytes("r")
    Queue.AddBytes("e")
    Queue.AddBytes("y")
    Queue.AddBytes("o")
    Queue.AddBytes("u")  
   
    Dim str() As Byte = "Something #"
    For i = 1 To 10
        Queue.AddBytes(str)
        Queue.AddBytesToLastItem(NumberFormat(i, 0, 0))
    Next  
   
    Log("Size before dequeue: ", Queue.Size, " items")
    Do While Queue.Size > 0
        Log("1-",Queue.FirstItem)
        Queue.RemoveFirst
    Loop
   
    Log("Size after dequeue: ", Queue.Size, " items")
    Log("StackBufferUsage: ", StackBufferUsage)
End Sub
It looks perfect. What I need, because the StackBufferUsage is:312

Please how can I get with queue the string "hallo how are you" without JoinString function? I will send string via classic serial.

EMEXES - Thank you for your help and question, I am learning how to work with string and bytes and B4R. It something different, its very nic, but I am learning.

Thank you very much
Best regards
p4ppc
 

miker2069

Active Member
Licensed User
Dear friends,

I am trying:
B4X:
Private Sub AppStart
    Serial1.Initialize(115200)
    Log(" ") : Log("AppStart")
    Queue.AddBytes("h")
    Queue.AddBytes("a")
    Queue.AddBytes("l")
    Queue.AddBytes("l")
    Queue.AddBytes("o")
    Queue.RemoveFirst
    Queue.AddBytes("h")
    Queue.AddBytes("o")
    Queue.AddBytes("w")
    Queue.AddBytes("a")
    Queue.AddBytes("r")
    Queue.AddBytes("e")
    Queue.AddBytes("y")
    Queue.AddBytes("o")
    Queue.AddBytes("u")
 
    Dim str() As Byte = "Something #"
    For i = 1 To 10
        Queue.AddBytes(str)
        Queue.AddBytesToLastItem(NumberFormat(i, 0, 0))
    Next
 
    Log("Size before dequeue: ", Queue.Size, " items")
    Do While Queue.Size > 0
        Log("1-",Queue.FirstItem)
        Queue.RemoveFirst
    Loop
 
    Log("Size after dequeue: ", Queue.Size, " items")
    Log("StackBufferUsage: ", StackBufferUsage)
End Sub
It looks perfect. What I need, because the StackBufferUsage is:312

Please how can I get with queue the string "hallo how are you" without JoinString function? I will send string via classic serial.

EMEXES - Thank you for your help and question, I am learning how to work with string and bytes and B4R. It something different, its very nic, but I am learning.

Thank you very much
Best regards
p4ppc
Could you perhaps start with a predefine buffer of some size like buffer(32) as byte and just set each character at the appropriate index as necessary? You can then send the buffer and if you have more than 32 bytes of data to send you reset the buffer and fill it again, and send, and so on...
 

petr4ppc

Active Member
Licensed User
Miker,

please. If I will have for example buffer(5) as byte, then how I send string "hallo" via serial? I must then join eachbyte and it does it mean that I am returning back to problematic with memory...it is true? i need then send string "hallo" via serial...

I am trying your words, but I have mistake, I see nothing, please can you check my declaration?:

B4X:
Dim tmp(5) As Byte
Dim xbyte As Byte
xbyte=0

    Do While Queue.Size > 0
        xbyte=xbyte+1
        Log("X-",Queue.FirstItem)
        tmp(xbyte)=Queue.FirstItem     
        Queue.RemoveFirst   
    Loop

Log("tmp:",tmp) ' here is my string
 
Last edited:

petr4ppc

Active Member
Licensed User
Miker,

most often have string length <= 20
but sometimes the string can have length <=200
 

emexes

Well-Known Member
Licensed User
[/QUOTE]
If you always use .AddBytesToLast then effectively the Queue will act like StringBuilder, adding bytes to a single Queue item, which you can access at any time using Queue.FirstItem(), or more likely something like:
B4X:
Queue.AddBytesToLast("H")
Queue.AddBytesToLast("a")
Queue.AddBytesToLast("l")
Queue.AddBytesToLast("l")
Queue.AddBytesToLast("o")
Queue.AddBytesToLast("!")

Dim bc As ByteConverter
Dim JoinedString As String = bc.StringFromBytes(Queue.FirstItem())    'might not need the ()
which sounds like what you want... except for:
B4X:
Queue.RemoveFirst
which will have the effect of removing the first item in the Queue, which is probably the (entire) string that you have been building up.

Why the .RemoveFirst???

The roll-your-own approach of Miker2069 is a quite reasonable solution too. You can write it to do just whatever you need it to do - no more, and no less. Cf the Queue module, which is more functional than you require because it written to cope with a wider variety of situations, and I think that this generality is causing confusion, eg concept of Queue being items, not bytes.
 
Top