Fixes for memory corruption in Arduino Strings

While Arduino Strings on AVR are very very safe, even when they run out of memory, (see my tutorial on Taming Arduino Strings )
there are two statements that can cause memory corruption
str += str; // concat str to itself (Edit)
and
statements like
String(1.0,40); // and similar were result exceeds the local buf[33]

These have been fixed in this version of WString.cpp for AVR boards.

A pull request has been created on the Arduino AVR core.
Edit - New development of String takes place on GitHub - arduino/ArduinoCore-API: Hardware independent layer of the Arduino cores
In that code there are fixes for these two issues. So the pull request was closed.

BUT.. both these issues have been known for some time and not fixed so you may need
Edit - While waiting for the ArduinoCore-API to be released you need
to apply the fix yourself by replacing the WString.cpp in arduino ...\hardware\arduino\avr\cores directory with the revised one above.

OR

Given how obscure the bugs are you could also just ignore this fix and just don't use
str += str; // i.e. don't try to double str by adding it to itself (Edit)
and don't create Strings from large floats with lots of decimal places specified.

1 Like

Does that include str += chr;?
Probably the biggest problematic use of Strings in Arduino is the loop people use to accumulate input from a Serial port:

  inputLine += Serial.read();
  inputLine += Serial.readString();

No it is much more obscure than that

String str = "abc";
str += str; // concat of String to itself

The first line += Serial.read(); will give un-expected results because Serial.read() returns an int.
inputLine += ((char) Serial.read());
works just fine. Using inputLine.reserve( ) prevents fragmentation.

inputLine += Serial.readString();
also work just fine, but creates a temporary String on the rhs which temporarily uses extra RAM. Almost always OK unless you are very low on available RAM or the input is very long.
When it does not work (out of RAM) you just end up with the inputLine unchanged. No crash on small AVR boards.
Again using inputLIne.reserve( ) prevents fragmentation