title: Arduino - What's the right way to store an array of String?
body: <p>I get an unpredicted behaviour of a program while trying to fill a dynamic array of String objects. I've tried to simplify the program, but couldn't figure out the cause.</p>
  
  <p>FYI: <code>debug()</code> and <code>debugLn()</code> print data to <code>Serial</code>, <code>debugMem()</code> prints free memory amount.</p>
  
  <p>So, the simplest version works as expected (the scenario - allocate a global array of 3 Strings, define 3 local variables and assign their values to array elements):</p>
  
  <pre><code>String* arr;
  
  void setup() {
    Serial.begin(9600);
  
    debugMem("1");
  
    String src = "abcdefghijk";
  
    arr = malloc(3 * sizeof(String));
  
    debugMem("2");
  
    String dest1 = src;
    String dest2 = src;
    arr[0] = src.substring(0);
    arr[1] = dest1.substring(0);
    arr[2] = dest2.substring(0);
  
    debugMem("3");
  
    dest1.setCharAt(1, 'z');
    dest2.setCharAt(1, 'x');
  
    debug(F("src: "));
    debugln(src);
    debug(F("src located at "));
    debugln((long)&amp;src);
    debug(F("dest1: "));
    debugln(dest1);
    debug(F("dest1 located at "));
    debugln((long)&amp;dest1);
    debug(F("dest2: "));
    debugln(dest2);
    debug(F("dest2 located at "));
    debugln((long)&amp;dest2);
    debug(F("arr[0]: "));
    debugln(arr[0]);
    debug(F("arr[0] located at "));
    debugln((long)(arr + 0));
    debug(F("arr[1]: "));
    debugln(arr[1]);
    debug(F("arr[1] located at "));
    debugln((long)(arr + 1));
    debug(F("arr[2]: "));
    debugln(arr[2]);
    debug(F("arr[2] located at "));
    debugln((long)(arr + 2));
    debugMem("4");
  }
  </code></pre>
  
  <p>Its output:</p>
  
  <pre><code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1787&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;1
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1753&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;2
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1683&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;3
  src: abcdefghijk
  src located at 2294
  dest1: azcdefghijk
  dest1 located at 2288
  dest2: axcdefghijk
  dest2 located at 2282
  arr[0]: abcdefghijk
  arr[0] located at 493
  arr[1]: abcdefghijk
  arr[1] located at 499
  arr[2]: abcdefghijk
  arr[2] located at 505
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1683&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;4
  </code></pre>
  
  <p>(Though I'm a bit confused with the addresses of src, dest1, dest2 that is greater then the total amount of 2048 bytes of RAM).</p>
  
  <p>The second version does actually the same (pushing values from local var to global array), but its behaviour is "completely different" (the scenario - init a dummy source string, parse it in a function, reallocating a global array to store parsed strings, assign a value from local variable to every array element):</p>
  
  <pre><code>String* phones;
  int phonesCount;
  
  void setup() {
    Serial.begin(9600);
  
    String reply = "1234567890,2345678901,3456789012";
  
    fillPhones(reply);
  }
  
  void loop() {
    debugln(F("loop"));
  
    for(int i = 0; i &lt; phonesCount; i++) {
      debug(F("Phone"));
      debugln(i);
      debug(F("Phone located at "));
      debugln((long)(phones + i));
      debug(F("Phone: "));
      debugln(*(phones + i));
    }
  }
  
  void fillPhones(String reply) {
    phonesCount = parsePhones(reply, phones);  
  }
  
  int parsePhones(String reply, String* &amp;phonesArray) {
    debugMem("1");
  
    phonesArray = NULL;
    int count = 0;
  
    int fromIndex = 0;
    int toIndex = 0;
    while(toIndex &gt;= 0) {
      debug(F("Phone index: "));
      debugln(count);
  
      toIndex = reply.indexOf(F(","), fromIndex);
      debug(F("Substring: "));
      debug(fromIndex);
      debug(F(".."));
      debugln(toIndex);
      debugMem("2");
  
      String entryPhone = reply.substring(fromIndex, toIndex);
      debugMem("3");
      debug(F("Phone to add: "));
      debugln(entryPhone);
      debug(F("Phone located at "));
      debugln((long)&amp;entryPhone);
  
      String* tmpArray = realloc(phonesArray, (count + 1) * sizeof(String));
      if(tmpArray == NULL) {
        break;
      }
      debug(F("Array allocated bytes: "));
      debugln((count + 1) * sizeof(String));
      debug(F("Array located at "));
      debugln((long)tmpArray);
      debugMem("4");
  
      phonesArray = tmpArray;
      debugMem("5");
  
      phonesArray[count] = entryPhone;
      debug(F("Added phone: "));
      debugln(phonesArray[count]);
      debug(F("Added phone located at "));
      debugln((long)(phonesArray + count));
      debugMem("6");
  
      count++;
      fromIndex = toIndex + 1;
    }
    debug(F("Total phones count:"));
    debugln(count);
  
    debugMem("7");
  
    return count;
  }
  </code></pre>
  
  <p>Its output:</p>
  
  <pre><code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1647&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;1
  Phone index: 0
  Substring: 0..10
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1647&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;2
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1634&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;3
  Phone to add: 1234567890
  Phone located at 2273
  Array allocated bytes: 6
  Array located at 623
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1626&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;4
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1626&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;5
  Added phone: 1234567890
  Added phone located at 623
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1613&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;6
  Phone index: 1
  Substring: 11..21
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1626&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;2
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1613&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;3
  Phone to add: 2345678901
  Phone located at 2273
  Array allocated bytes: 12
  Array located at 657
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1607&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;4
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1607&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;5
  Added phone: 2345678901
  Added phone located at 663
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1607&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;6
  Phone index: 2
  Substring: 22..-1
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1620&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;2
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1607&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;3
  Phone to add: 3456789012
  Phone located at 2273
  Array allocated bytes: 18
  Array located at 657
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1601&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;4
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1601&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;5
  Added phone: 3456789012
  Added phone located at 669
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1601&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;6
  Total phones count:3
  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;1614&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;7
  loop
  Phone0
  Phone located at 657
  Phone: 1234567890
  Phone1
  Phone located at 663
  Phone: ‚56789012
  Phone2
  Phone located at 669
  Phone: 3456789012
  </code></pre>
  
  <p>As you can see, while there are no observable fails on filling, it outputs shit in a loop.</p>
  
  <p>I wish to know what the right way to add a String to a (dynamic) array of Strings is. Why does the first version work fine? Is it just because it's so small/simple?</p>
  
  <p>PS1: short version of the first example (w/o debug output):</p>
  
  <pre><code>String* arr;
  
  void setup() {
    Serial.begin(9600);
  
    String src = "abcdefghijk";
  
    arr = malloc(3 * sizeof(String));
  
    String dest1 = src;
    String dest2 = src;
    arr[0] = src.substring(0);
    arr[1] = dest1.substring(0);
    arr[2] = dest2.substring(0);
  
    dest1.setCharAt(1, 'z');
    dest2.setCharAt(1, 'x');
  }
  </code></pre>
  
  <p>PS2: short version of the second example (with min debug output):</p>
  
  <pre><code>String* phones;
  int phonesCount;
  
  void setup() {
    Serial.begin(9600);
  
    String reply = "1234567890,2345678901,3456789012";
  
    fillPhones(reply);
  }
  
  void loop() {
    debugln(F("loop"));
  
    for(int i = 0; i &lt; phonesCount; i++) {
      debug(F("Phone"));
      debugln(i);
      debug(F("Phone located at "));
      debugln((long)(phones + i));
      debug(F("Phone: "));
      debugln(*(phones + i));
    }
  }
  
  void fillPhones(String reply) {
    phonesCount = parsePhones(reply, phones);  
  }
  
  int parsePhones(String reply, String* &amp;phonesArray) {
    phonesArray = NULL;
    int count = 0;
  
    int fromIndex = 0;
    int toIndex = 0;
    while(toIndex &gt;= 0) {
      toIndex = reply.indexOf(F(","), fromIndex);
  
      String entryPhone = reply.substring(fromIndex, toIndex);
  
      String* tmpArray = realloc(phonesArray, (count + 1) * sizeof(String));
      if(tmpArray == NULL) {
        break;
      }
      phonesArray = tmpArray;
  
      phonesArray[count] = entryPhone;
  
      count++;
      fromIndex = toIndex + 1;
    }
    return count;
  }
  </code></pre>