How to split a string with space and store the items in array?

Even with chars the inevitable happens because base keep increasing so the I/O char lengths you are processing, for each num are increasing (Ignoring the fact that num is increasing each loop so eventually the number of number being processed will exceed the UNO/Mega's memory)
The first seq starts 1,2,3
Later sequences start 1013,1014 and so are ~3 times as long for any given num
After enough loops the base sequence will get to numbers like 30010, 30011, 30011, ~5times as long and when base wraps around to -ves it will be longer.

However the String version does use more memory (and much more the way you have written it) and does seem to be doing some strange things with memory allocation.
So still a very good example.

@drmpf It is not about the numbers, it could have been something else. What causes the problem is that two or more instances of "String" (or anything else using dynamic memory allocations) takes turns in expanding memory consumption. This will cause memory fragmentation and eventually malfunction. If the sketch had used statically allocated char arrays, the number sequences would (in length) have been able to grow past the capabilities of the "String" variables because no memory would have been lost to fragmentation.

EDIT: Untested example that should do the same as the "String" thing above:

uint16_t initialFree, size1, size2;
char *ptr1, *ptr2;

void setup()
{
  Serial.begin(9600);
  initialFree = freeRam(); //Implement from above
  size1 = 5;
  size2 = 10;
  ptr1 = (char*)malloc(size1);
  ptr2 = (char*)malloc(size2);
}

void loop()
{
  if (size1 + size2 + 10 < initialFree)
  {
    size1 += 5;
    ptr1 = (char*)realloc(ptr1, size1);
    size2 += 5;
    ptr2 = (char*)realloc(ptr2, size2);
    if ((ptr1 == 0) || (ptr2 == 0))
    {
      Serial.print("Failing at: ");
      Serial.println(size1+size2-10);
    }
  }
  else
  {
    Serial.println("Success!");
  }
}

Yes indeed.

That's why you need to call reserve() on your String in the setup. That will protect you for some time.
of course most newbies don't (and veterans go the cString way)

PS: to explain this I had done this conceptual memory map explaining where the data gets relocated at every operation if you have 3 Strings without reserving first the memory and expand in turns by 1 char

we see in green the free blocks moving around, being reused, but growing along the way to a point where the last C increase just does not have anywhere to go despite that overall there would be enough memory for the 3 strings of that size.

That also explains why it's slow and costly to do because you have all this moving around to do.

➜ knowledge is power :wink:
➜ use cStrings or use reserve() if you want to use Strings and then all remains very tidy and you have plenty of memory left

1 Like

@J-M-L Beautiful illustration of the "problem" and it should be standard lecture for everyone using dynamic memory on AVR based boards. Yes, "String.reserve()" will reduce the issue but it will only be "stable" if the reserved heap is considered a limit which is never exceeded - otherwise it is only a false sense of security.

Well if you had statically allocated a char buffer of the same size, writing beyond that limit would likely crash. With a String, if memory is available, then you keep cranking…

But always best to keep an eye on what’s going on.

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