How to use Arduino Strings

Arduino Strings have been getting some bad press, but it turns out they are not that bad and are very usable in sketches. My tutorial Taming Arduino Strings goes into the details. The summary is :-

For small sketches with a few Strings, just use them as convenient.

For small sketches with a few Strings, just use them. The good news is if you are using an UNO or Mega2560, then using Strings is extremely safe, even if you run out-of-memory. If you run out-of-memory, you will just not get all the text in the Strings that you expect. The program will continue to run. See What happens when UNO runs out of heap memory
Other boards will have more memory available and so you are unlikely to have memory problems using a few Strings.

For large sketches OR lots of Strings OR if you think you are having memory problems

If you have a large sketch, with lots of Strings OR you are concerned about possible memory problems, then following the guidelines below will make your sketch reliable and safe.

Guidelines for Using Arduino Strings

  • Declare long lived Strings as globals and reserve( ) space in setup(), starting with the smallest to the largest. Check the return from the last largest reserve( ) to see that you have enough memory for all the Strings
  • If you have created Strings in the loop() method, they are long lived, move them to Globals and repeat step 1.
  • Pass all Strings arguments to methods, as const String& . For results pass a String& result, that the method can update with the result. i.e. void strProcessing(const String &input1, const String &input2, ,, String &result) {..} See Using String& for arguments
  • Set the IDE File → Preferences Compiler Warning to ALL and watch for warning: passing 'const String' as 'this' argument discards qualifiers [-fpermissive] messages in the compile window. This says you are trying to modify a const String& arg.
  • Do string processing in small compact methods. In these methods use local Strings in preference to local char. These methods will completely recover all the heap and stack used by their local Strings and other variables on exit. See String versus char[]
  • Do not use the String + operator at all and avoid using the String(...) constructors as these create short lived temporary Strings. Use = and += operators or concat( ), as in result += “str”; result += 'c'; result += number; etc. See Minimizing Memory Usage
  • To monitor for Low Memory and fragmentation, add a StringReserveCheck to at least the last largest String reserve( ). Add StringReserveCheck to other Strings as necessary. See Using StringReserveCheck (download and install StringReserveCheck.zip)
  • If your Arduino program uses the Web e.g. ESP32 / EPS8266 webserver/httpClient, then the underlying web support libraries already use lots of Strings. If you project is suppose to run for a long time, add a periodic automatic reboot. See ESP32/ESP8266 Adding Periodic Automatic Reboots

Would appreciate to see few working examples on Arduino UNO.

Here is the bare bones Uno Strings out of memory sketch

/*
  MemFrag_ex4.  without using StringReserveCheck
  Example of UNO out-of-memory with Strings
  Sketch keeps running, just some String text missing

  by Matthew Ford
  Copyright(c)2021 Forward Computing and Control Pty. Ltd.
  This example code is in the public domain.

  www.forward.com.au/pfod/ArduinoProgramming/ArduinoStrings/index.html
*/

String string1;
String string2;
String string3;

void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.print(i); Serial.print(' ');
    delay(500);
  }
  Serial.println();
  Serial.println(F("Memory Fragementation Example 4 - Out Of Memory"));
  string2.reserve(32); // do reserve in order smallest first string2
  string1.reserve(600); // next largest string1
  if (!string3.reserve(930)) { // do largest last and check its return
    while (1) { // stop here and print repeating msg
      Serial.println(F("Strings out-of-memory"));
      delay(3000); // repeat msg every 3 sec
    }
  }
  string1 = F("string1 initial value");
  string3 = F("string3 initial value");
}

void printDegC(float value, String& result) {
  String title = F("This is the temperature in the boiler room ");
  String units = F("degC");
  formatResult(title, units, value, result);
}
void formatResult(const String& title, const String& units, float value, String& result) {
  result = title;
  result += String(value, 1); //temp to 1 decimal only
  result += units;
}

void loop() {
  float temp = 27.35;
  printDegC(temp, string2);
  Serial.println(string2);
}

the output is just 27.4degC. There is not enough heap memory to add the
This is the temperature in the boiler room text.

Memory Fragementation Example 4 - Out Of Memory
27.4degC
27.4degC
27.4degC
 . . .

Here is the same sketch with the StringReserveChecks added (MemFrag_ex4.ino in the tutorial)

/*
  MemFrag_ex4.
  Example of UNO out-of-memory with Strings
  Sketch keeps running, just some String text missing
  
  by Matthew Ford
  Copyright(c)2021 Forward Computing and Control Pty. Ltd.
  This example code is in the public domain.

  www.forward.com.au/pfod/ArduinoProgramming/ArduinoStrings/index.html
*/

// Download the StringReserveCheck.zip file
// https://www.forward.com.au/pfod/ArduinoProgramming/ArduinoStrings/StringReserveCheck.zip
// and install it using the IDE Sketch → Include Library → Add .ZIP library...
#include <StringReserveCheck.h>

String string1;
StringReserveCheck string1Check;
String string2;
StringReserveCheck string2Check;
String string3;
StringReserveCheck string3Check;

void setup() {
  Serial.begin(9600);
  for (int i = 10; i > 0; i--) {
    Serial.print(i); Serial.print(' ');
    delay(500);
  }
  Serial.println();
  Serial.println(F("Memory Fragementation Example 4 - Out Of Memory"));
  string2.reserve(32); // do reserve in order smallest first string2
  string2Check.init(string2, Serial); // init( ) will print a msg if memory is low and checkReserve( ) will print a msg
  string1.reserve(600); // next largest string1
  string1Check.init(string1); // checkReserve( ) will not print any msgs, you need to check its return value
  if (!string3.reserve(930)) { // do largest last and check its return
    while (1) { // stop here and print repeating msg
      Serial.println(F("Strings out-of-memory"));
      delay(3000); // repeat msg every 3 sec
    }
  }
  if (!string3Check.init(string3, Serial)) {    // check return for low memory
    Serial.println(F("Memory Low after reserves()"));
  }
  string1 = F("string1 initial value");
  string3 = F("string3 initial value");
}

void printDegC(float value, String& result) {
  String title = F("This is the temperature in the boiler room ");
  String units = F("degC");
  formatResult(title, units, value, result);
}
void formatResult(const String& title, const String& units, float value, String& result) {
  result = title;
  result += String(value, 1); //temp to 1 decimal only
  result += units;
}

void loop() {
  float temp = 27.35;
  printDegC(temp, string2);
  Serial.println(string2);
  string1Check.checkReserve(); // init(string1,Serial); was specified so msg printed
  if (!string2Check.checkReserve()) { // check return,  init(string2,Serial); was specified so msg also printed
    Serial.print(F("string2 reserve too small. Current length():")); Serial.println(string2.length());
  }
  if (!string3Check.checkReserve()) { // init(string3); // no output specified, check return
    Serial.print(F("string3 reserve too small. Current length():")); Serial.println(string3.length());
  }
  Serial.println();
}

The output is now

Memory Fragementation Example 4 - Out Of Memory
!! Low memory available, stability problems may occur.
Memory Low after reserves()
27.4
!! reserve() NOT large enough for String '27.4' Current len:4
string2 reserve too small. Current length():4
reserve() large enough for String 'string3 in...' Current len:21

27.4degC
!! reserve() NOT large enough for String '27.4degC' Current len:8
string2 reserve too small. Current length():8
reserve() large enough for String 'string3 in...' Current len:21

Using the StringReserveCheck class clearly shows the low heap memory on start up
!! Low memory available, stability problems may occur.

Memory Low after reserves()
and the string2Check.checkReserve() shows that not enough memory was reserved for string2.
While the check on string3 shows enough was reserved for it.
checkReserve() returns true or false but can also be configured to print a message as well

There are a number of other examples in the Taming Arduino Strings tutorial as well as memory stack diagrams showing how fragementation arises and how to avoid it.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.