Memory management of NXC strcat
Memory management of NXC strcat
How exactly does strcat manage memory in NXC? I'm writing a program to receive packets of data over Bluetooth from a computer, and I'm simply concatenating each new packet that comes in to a single string. The problem is that the program crashes after the string's length exceeds a little over 6000. I saw somewhere else on Mindboards that an NXC program has 32kB of memory available during execution, so I came to the conclusion that strcat must be the source of the problem since the string is not large enough to be using up that amount of memory. So what is the best way to combine the packets of data so that the program does not exceed its memory limitations?
Re: Memory management of NXC strcat
Yeah, must be
Gives the following NBC output:
-----
Here it is with the
NBC:
strcat()
. Watch:
Code: Select all
task main()
{
string a, b, c;
c = strcat(a, b);
}
Code: Select all
dseg segment
a byte[]
b byte[]
strcat_dest byte[]
strcat_src byte[]
retval byte[]
bufstrcat byte[]
strbuf byte[]
dseg ends
thread main
mov strcat_dest, a
strcat strbuf, b
mov strcat_src, strbuf
strcat bufstrcat, strcat_dest, strcat_src
mov strcat_dest, bufstrcat
mov a, bufstrcat
mov retval, bufstrcat
strcat strbuf, retval
exit -1, -1
endt
Here it is with the
+
operator:
Code: Select all
task main()
{
string a, b, c;
c = a + b;
}
Code: Select all
dseg segment
a byte[]
b byte[]
strcat_dest byte[]
strcat_src byte[]
strbuf byte[]
dseg ends
thread main
mov strcat_dest, a
strcat strbuf, b
mov strcat_src, strbuf
strcat strbuf, strcat_dest, strcat_src
exit -1, -1
endt
Last edited by muntoo on 18 Jun 2011, 22:19, edited 1 time in total.
Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE
Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
-
- Posts: 358
- Joined: 01 Oct 2010, 06:37
- Location: Denmark
- Contact:
Re: Memory management of NXC strcat
As shown in muntoos post, you have to be very careful when you are dealing with large strings/arrays because it ends up making temporary variables.
To make matters worse, in NBC there is no such thing as scope, all variables are global/static so even when it goes out of scope in NXC it does not get cleared. And it is "impossible" to clear them, since you don't have access to them. (Well, there is a dirty trick, run the function again but with an empty array, depending on the function you might be able to clear most of them.)
To make matters worse, in NBC there is no such thing as scope, all variables are global/static so even when it goes out of scope in NXC it does not get cleared. And it is "impossible" to clear them, since you don't have access to them. (Well, there is a dirty trick, run the function again but with an empty array, depending on the function you might be able to clear most of them.)
My blog: http://spillerrec.dk/category/lego/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
Re: Memory management of NXC strcat
I wonder, would writing the input to a file whilst it is coming in be too slow?
A sophistical rhetorician, inebriated with the exuberance of his own verbosity, and gifted with an egotistical imagination that can at all times command an interminable and inconsistent series of arguments to malign an opponent and to glorify himself.
Re: Memory management of NXC strcat
I would recommend using a simple NBC asm block that uses the strcat opcode to concatenate the new input string to your buffer. You will need one temporary byte array to hold the output of strcat and then copy that into your original buffer. After that you can empty the temporary with arrinit.
John Hansen
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Memory management of NXC strcat
Wouldn't this work:afanofosc wrote:I would recommend using a simple NBC asm block that uses the strcat opcode to concatenate the new input string to your buffer. You will need one temporary byte array to hold the output of strcat and then copy that into your original buffer. After that you can empty the temporary with arrinit.
Code: Select all
task main()
{
string a = "abcd";
string b = "efgh";
string c;
asm
{
// c = a + b;
strcat c, a, b
}
}
Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE
Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
Re: Memory management of NXC strcat
In the OP's case he has something like this:
So he has to have a third buffer to store the results of adding new_data to the end of large_buffer and then he needs to copy that back into a larger version of large_buffer. You can't use large_buffer as both an input and an output in strcat or you will overwrite your source before you copy it to your destination. The problem with strcat is that it is an inline function that takes 2 string input arguments and returns a string so you have the 2 variables you pass in, the 2 local variables that get a copy of your inputs, and the local return value variable and then a string buffer temporary that holds the return value of all string functions before the value is assigned to the LHS of the string expression. If I had a better optimizer these temporaries/locals would all be removed. If I were really clever and ambitious I could add compiler code that empties out any local arrays/strings when they go out of scope or are "released" by the compiler.
John Hansen
Code: Select all
task main()
{
string large_buffer, tmp;
string new_data;
// read data from bluetooth
//append it to large_buffer
asm {
strcat tmp, large_buffer, new_data
mov large_buffer, tmp
arrinit tmp, 0, 0
}
}
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Memory management of NXC strcat
Wouldafanofosc wrote:You can't use large_buffer as both an input and an output in strcat or you will overwrite your source before you copy it to your destination.
arrbuild
work, then? I use this in NXC: Code: Select all
#define push(out,val) ArrayBuild(out, out, val);
OT: Say, have you read the 'Dragon Book'? Apparently, it's the must read book for compiler writers. (It's on my to-read list.)
Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE
Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
Re: Memory management of NXC strcat
arrbuild is the same as strcat except that one is designed to work with null terminated byte arrays (strcat) while the other is designed to work with any old kind of array. They both have the same limitation that you can't use any of the inputs as the output or it will be overwritten (actually reallocated to a different memory location) before you copy the input to the output.
John Hansen
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: Memory management of NXC strcat
Hmm. I tried your code and it ends up freezing my NXT. I have no clue why. Here is my code:afanofosc wrote:In the OP's case he has something like this:
So he has to have a third buffer to store the results of adding new_data to the end of large_buffer and then he needs to copy that back into a larger version of large_buffer. You can't use large_buffer as both an input and an output in strcat or you will overwrite your source before you copy it to your destination. The problem with strcat is that it is an inline function that takes 2 string input arguments and returns a string so you have the 2 variables you pass in, the 2 local variables that get a copy of your inputs, and the local return value variable and then a string buffer temporary that holds the return value of all string functions before the value is assigned to the LHS of the string expression. If I had a better optimizer these temporaries/locals would all be removed. If I were really clever and ambitious I could add compiler code that empties out any local arrays/strings when they go out of scope or are "released" by the compiler.Code: Select all
task main() { string large_buffer, tmp; string new_data; // read data from bluetooth //append it to large_buffer asm { strcat tmp, large_buffer, new_data mov large_buffer, tmp arrinit tmp, 0, 0 } }
John Hansen
Code: Select all
task main ()
{
string URL = "http://rss.cnn.com/rss/cnn_topstories.rss";
string proceed;
int URLlength = StrLen(URL);
string URLlengthAsString = NumToStr(URLlength);
SendResponseString(0, URLlengthAsString);
for (int idx = 0; idx < URLlength; idx += 58) {
string msg = SubStr(URL, idx, 58);
SendResponseString(0, msg)
while (ReceiveMessage(0, true, proceed) != LDR_SUCCESS);
}
string sizeAsString;
while(ReceiveMessage(0, true, sizeAsString) != LDR_SUCCESS);
long size = StrToNum(sizeAsString);
NumOut(0, LCD_LINE1, size);
long numBytesWritten = 0;
string message, packet, tmp;
while(numBytesWritten < size) {
while(ReceiveMessage(0, true, packet) != LDR_SUCCESS);
asm {
strcat tmp, message, packet
mov message, tmp
arrinit tmp, 0, 0
}
numBytesWritten += StrLen(packet);
}
NumOut(0, LCD_LINE4, StrLen(message), true);
}
Who is online
Users browsing this forum: No registered users and 1 guest