I have narrowed down a crash in my code to a just a small bit, but I still can't figure out exactly why it's crashing. I've wasted 12 hours of my life on this, so any insight would be appreciated! I am running on the Arduino Mega 2560. This code doesn't really do anything useful, but demonstrates the problem. Below the code is the output that I get immediately after reset. The output is correct for the first two times through loop(), but the third loop prints junk and then it crashes. Crazy, huh?
I've identified two things that "fix" the problem, but I can't fathom why. First, removing "String Hex" makes it run correctly (it's not even used anywhere, so I can't fathom why having it in or not makes any difference at all!). Second, using itoa() instead of sprintf() also appears to work correctly, even with "String Hex" still being declared... but again, why? And why does it work correctly the first two times through and crash on the third?
Thanks for any help!
void StupidTest();
// the setup routine runs once when you press reset:
void setup() {
Serial.begin(115200);
pinMode(13, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
StupidTest();
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
void StupidTest() {
String Hex; // removing this unused String fixes the problem
String HexFull;
uint8_t args[6][4];
int c = 0;
memset(args, 0xFF, sizeof(args));
// loop through array and print out each byte in hex
for (int a = 0; a < 6; a++) {
for (int b = 0; b < 4; b++) {
char str[20];
// put the uint08 into a uint16
unsigned int x = args[a][b];
sprintf(str, "%X ", x);
// itoa(x, str, 16); // using itoa() instead of sprintf() fixes the problem
HexFull += str;
// HexFull += " ";
Serial.println(HexFull);
}
}
}
Unless you have applied a patch to the memory handling (the free function iirc) you will probably be suffering from the bug that shows up through use of String. Avoid using String and stick to char and you wil avoid the memory handling bug. That said, there is limited memory as Nick has reffered you to.
Unbelievable. Whoever is in charge of the Arduino website needs to make a note of that in the online Reference. A simple one sentence note on the String class ("String currently contains deadly bugs") would have saved me a ton of grief (and other people, I imagine).
As far as the memory limitations, I thought that might be the issue so I tried using the little get_free_memory() function posted here: http://forum.pololu.com/viewtopic.php?f=10&t=989&view=unread#p4218. It didn't indicate much of a problem, but obviously it can't run within sprintf() or help me detect memory handling bugs.
Anyway, in hindsight it seems like avoiding use of the heap in general seems like a good idea. I'll try out the PString and Streaming libraries, it seems like they might provide a much better starting point than String anyway.
Thanks for the responses! (And sorry for the sloppy reading of the "before you post" thread, ... but I did read most of it! )
I'll try out the PString and Streaming libraries, it seems like they might provide a much better starting point than String anyway.
PString is not significantly different from WString. It still allocates and deallocates memory (which is where the bug is). It is not a magical way to avoid using char arrays and doing the work yourself.
PString is not significantly different from WString. It still allocates and deallocates memory (which is where the bug is). It is not a magical way to avoid using char arrays and doing the work yourself.
I'm sorry, but you are wrong. I can tell you confidently that PString does no explicit memory allocation at all (everything is on the stack). PString requires you to pass it a pointer to a char array in its constructor and that is the only memory it works with. How you create that char array is up to you. So yes, you could create that array on the heap, but that wouldn't make your statement about PString true, since PString has nothing to do with how you create your char array.
Using PString as a starting point, I added the functionality that String provides that is missing in PString. Now the only difference between String and my PString is in how you instantiate it. With PString, it is like this:
char str[32];
PString Str(str, 32);
The great thing about PString is that it is impossible to write past the end of your array (it just truncates), which is certainly not true if you do everything as C-style char array manipulations. I added a Serial.print("") to PString::write() which prints a warning when a string has been truncated (rather than just crashing). PString also is quite cheap (I believe it is 4-bytes per instance and it adds next to nothing additional to your program size). My point is that PString is a beautiful thing; everyone should absolutely be using it. C-style char array manipulations are cumbersome and dangerous and there is no reason to still be doing things that way (unless you really need that extra 4 bytes).
Very weird but in my uno code works perfect (more than 3 min already)
That is weird. Anyone care to verify my results with a Mega? Not that it matters since we already know what the problem is. I've been stable as can be now that I'm using PString.
The sketch runned like 3-4 days perfectly (I forget it and remembered after seing the blinking led, checked and everything was perfect). So no issues on original sketch without any change.
Okay, so it definitely works without issue on the Uno, and it definitely crashes on the Mega. Thanks for checking, SurferTim, and that is funny that just swapping the order of declaration for the two Strings fixes it.
Yeah, but are you using 1.0.1 with the bug fix included?
OP may be using version prior to 1.0.1.
The memory allocation bug is present in 1.0.1, which is what I am using.
I don't think the problem is with the Mega. I tested again in my 2560 clone and 1280 original. And no problems at all: http://screencast.com/t/F06Pio65Hr
Writing this message and uploding the video 3 minutes elapsed and still no issues. The only thing I have replaced in the IDE is the WinAVR version.