Limited memory and String variable

Hello!
I ran into a strange problem while executing the project. After entering 600 characters into the String variable and performing the operation on them, I cleared the string so that it would not take up valuable memory, but when I repeated it, I entered another string of 600 characters, only about 400 was entered. I came to the conclusion that the problem is memory clogging...
Have you had such a problem? If so, how to solve it.
Thank you in advance!

The general advice in this forum would be to use strings (lowercase s) instead of Strings (uppercase S) because of the limited memory available to most Arduinos. However, some users will suggest using Strings but in a different way

strings are arrays of chars terminated by a zero
Strings are objects created using the String library

Expect multiple replies to this topic explaining why both are the best solution

Let battle commence

1 Like
  1. Please post your code. Easiest is to use edit -> copy for forum in the IDE and next paste it in a reply.
  2. Which board are you using?
  3. Please explain why you think that this belongs in the storage section of the forum? There might be a section where your issue gets better exposure.
1 Like
  1. My code takes 400 lines and I don't want it to flow to the net, I will just give you an example.
  2. I am using the String.h function
  3. I created the post in this section because the name is appropriate to the problem (at least I think so. I might be wrong)
String serial;
serial = Serial.readStringUntil('\n'); //for example, takes 600 characters
...
serial = "";
serial = Serial.readStringUntil('\n'); //but here takes only 400 characters, even though the user enters 600
...
serial = "";

I also used the function myString.remove (index) but the effects were the same.

@black338out, your topic has been moved to a more suitable location on the forum; at least I think it's more suitable.

1 Like
  1. Please post the full code.
  2. I asked which board, not which library :wink:

Can you give us a broader view ?
Why do you want to read 600 bytes ? What is it for ?

Please answer the question which board you use. We don't mind code of a few thousand lines.
If you want to do that with a Arduino Uno, then it is not possible.
Perhaps a Raspberry Pi is more suitable for your project.

I am using an arduino nano board. I need 600 characters long to send information:
program on PC -> usb -> arduino
I would like to know how to remove data from a string to keep it from taking up memory.
Unfortunately, I can't send the code :disappointed:

Why not ?

Is this so important?

String serial;

void setup() {
  Serial.begin(38400);
}

void loop() {
  
  serial = Serial.readStringUntil('\n');
  if(serial != "")
  {
    Serial.println(serial);
    serial = "";
    delay(5000);
  }
}

1200 chars
WB37OtSiYQozAduL67aExvGIKvlXh8FDVVHNq3Cwtzo2uT3xfprBfw7JEeZ60bNPv0QrWRBLTT3gKffIJhHOZTxAlEbCyvXf0IAV8bBgkqAt7oSmEi6qSh2vDydZZfkFUb2sZUaAPTkOxgbhXf26vVHQnrsQrrkCArFN76j74IFPW1czPyj2V78IYl9ibyj1UI3X6aL5ArUzRPOfCD8JxIkbtcLuBoODKv9zYW29InASvADVEGRgfZxABjXzjvtKoDqUsh66kYxuBSHVsum8u4RpkY9Uy2u3raiQxszJiIoDZayvKGBa5YgdD63XzPmF3I5Xem5DNNRq27GrqqR9soCA0OQ8Be1jhP1WouSBFwqVamnXI3Cdc6XqYOCJG4Vi235rHA0LpkWmR51cLW4fjBLxlVbskioPuL1ze5fONVLTuqqFzRtNQqXM7QLBZhKKvU4sotdxBBylcSMoSO2If2aCy0vVX8SjEcrxsAHCE1rcZUJm04D4ofHVtefpbWQj9XX7bOngE1aTwdwJXWHadacc6Wszeqtn4CKDBRJJQfwssB6GKxTeDZyUx8h5raZwIZnDMneCbGZCjMjQ2wTISn2UWB37OtSiYQozAduL67aExvGIKvlXh8FDVVHNq3Cwtzo2uT3xfprBfw7JEeZ60bNPv0QrWRBLTT3gKffIJhHOZTxAlEbCyvXf0IAV8bBgkqAt7oSmEi6qSh2vDydZZfkFUb2sZUaAPTkOxgbhXf26vVHQnrsQrrkCArFN76j74IFPW1czPyj2V78IYl9ibyj1UI3X6aL5ArUzRPOfCD8JxIkbtcLuBoODKv9zYW29InASvADVEGRgfZxABjXzjvtKoDqUsh66kYxuBSHVsum8u4RpkY9Uy2u3raiQxszJiIoDZayvKGBa5YgdD63XzPmF3I5Xem5DNNRq27GrqqR9soCA0OQ8Be1jhP1WouSBFwqVamnXI3Cdc6XqYOCJG4Vi235rHA0LpkWmR51cLW4fjBLxlVbskioPuL1ze5fONVLTuqqFzRtNQqXM7QLBZhKKvU4sotdxBBylcSMoSO2If2aCy0vVX8SjEcrxsAHCE1rcZUJm04D4ofHVtefpbWQj9XX7bOngE1aTwdwJXWHadacc6Wszeqtn4CKDBRJJQfwssB6GKxTeDZyUx8h5raZwIZnDMneCbGZCjMjQ2wTISn2U

See my tutorial on Taming Arduino Strings which will show you how to reserve space and avoid memory fragmentation and check to see if fragmentation is occurring.
As an alternative you can use my SafeString library when gives you similar functionallity as Strings but with much better error checking then strings (small s).
The SafeString library includes a non-blocking replacement for readStringUntil( );
See Arduino to Arduino via Serial for example code.
You can also check out Arduino Software Solutions for various examples of reading from Serial with the pros and cons of each.

1 Like

Actually is you want to 'recover' the memory used by your 600 char String, replacing it with string (small s, char[ ] ) won't help.
You need to malloc your own buffer and then free it after you have finished with it.
Try this

// https://forum.arduino.cc/t/limited-memory-and-string-variable/868490/9

// download SafeString V4.1.5+ library from the Arduino Library manager or from
// https://www.forward.com.au/pfod/ArduinoProgramming/SafeString/index.html
// includes millisDelay also
#include "SafeString.h"
#include "millisDelay.h"

millisDelay freeBufferTimer;
unsigned long FREE_BUFFER_DELAY_MS = 10000;

char* buffer;
const size_t BUFFER_SIZE = 602;// 600 + \n + \0
void setup() {
  Serial.begin(38400);
  for (int i = 10; i > 0; i--) {
    Serial.print(i); Serial.print(' '); delay(500);
  }
  Serial.println();
  SafeString::setOutput(Serial); // enable error msgs

  buffer = (char*)malloc(BUFFER_SIZE); // 600 + \n + \0
  if (!buffer) {
    Serial.println(F("Out of memory"));
  }
  buffer[0] = '\0'; // clear it to start with
  freeBufferTimer.start(FREE_BUFFER_DELAY_MS);
}

void freeBuffer() {
  free(buffer);
  buffer = NULL;  // mark as gone
}

void loop() {
  if (freeBufferTimer.justFinished()) { // free it after 10sec
    freeBuffer();
  }

  if (buffer) { // not gone
    cSFPS(sfBuffer, buffer, BUFFER_SIZE); // wrap the buffer is a SafeString which will keep it '\0' terminated
      // and protect against buffer overflow and let you use String type funs on it
    if (sfBuffer.readUntil(Serial, '\n')) {
      // found \n OR buffer full
      if (!sfBuffer.endsWith('\n')) {
        Serial.println(F("Error buffer over flowed!!"));
      } else {
        // process buffer here
        Serial.println(sfBuffer);
      }
      sfBuffer.clear(); // for next line
    }
  } else {
    Serial.println(F("Buffer Freed!!"));
    delay(3000);
  }
}

The text is entered by the user. I just gave an EXAMPLE of the character string...

Are you saying that the user manually enters 600 characters ?

However they are entered, what do you do with them in the sketch ?

I think you have to learn to read first. Have a nice Sunday.

A program on the user's computer will do this. For example, it will convert a website into text that can be sent somewhere. The string will keep changing, it is not static.

The solution is interesting, unfortunately it is very extensive.

So despite

the user does not actually enter the text after all

If the job of the sketch is to pass on what it receives then why not pass on each character as it is received or pass on each chunk of say 64 bytes as they are received ?

+1 for this solution

Actually an 'advantage' of Serial.readStringUntil( ) is that it works in a tight loop and so any 'delays' in the rest of the loop do NOT cause missed chars.
But still agree with Bob, reading smaller blocks and keeping the rest of the loop fast while reading is the way to go.