0

I tried to run this code on my Arduino Uno clone (which has no function so far and is a shortend version of my programm):

String rules [16][5] ={
   {"B0 B5", "", "", "cs S0", "", },
   [...]
};

void setup() {
  Serial.begin(9600);
  String foo = "bar";
  Serial.println(foo);
}

void loop() {
}

I left the rules array out, but it is quite big. It isn't used yet, but it contains rules how to react on certain situations (which should be used later).

As the Arduino IDE gives the following after complilig:

Sketch uses 4316 bytes (13%) of program storage space. Maximum is 32256 bytes.
Global variables use 1174 bytes (57%) of dynamic memory, leaving 874 bytes for local variables. Maximum is 2048 bytes.

When I run this sketch there is nothing on the serial monitor. If it works, there should appear bar, but it does not. The Arduino sends only a linebreak over the serial, but no text.

When I remove some characters from that array so that there are about 900 bytes the script works and prints bar to the serial monitor.

So, aren't 874 bytes not enough to store a three-character string? Why does it need 900 bytes to store such a short string?

  • Because String instances are more than just their characters. – Ignacio Vazquez-Abrams Oct 29 '17 at 14:57
  • The very first Serial.print is usually lost (or garbage). Usual idiom to put a while (!Serial); in setup, before printing anything. Pay attention to the semi-colon. – user31481 Oct 29 '17 at 15:19
  • Please, post your real, working, complete sketch. You posted one incomplete sketch and the stats for another sketch unkown to us. Info is inconsistent. – user31481 Oct 29 '17 at 15:26
2

You are requesting 80 String objects.

Each String object allocates memory to store its data. When you provide a string constant that string constant data's length is used for the allocated data size (including the NULL character at the end), and the string constant data copied in.

On top of that you have a bunch of other data that is needed for the String class to do its work. The total size of a String object is 6 bytes.

So the memory you need for your array of Strings can be calculated as:

  • Let C be the total number of characters in all the string constants
  • Let N be the number of String objects in the array
  • Let T be the total number of bytes.

    T = N * 6 + C + N

With no string constant data that would be:

T = 80 * 6 + 80

That's 560 bytes already, before you even start thinking about putting in the string constant data.

Also you may like to add to that the fact that the compiler may (though I am not certain on this) be also copying the string constants into RAM first because they aren't forced into PROGMEM with the F() macro.

So since you only have 2KiB of RAM to begin with, and a quarter of that is instantly gobbled up with your array, you can see how things might not be too happy.

Oh, and the String's internal storage is allocated at run time, not compile time, so the compiler can't know that it'll overflow - only when you run the program will it overflow and things go horribly wrong.

So you need to ask yourself "Why do I even want an array of String objects?" and the answer is most certainly: "Under no circumstances do you ever want an array of String objects". In fact I am a strong advocate of never using String objects ever, for any reason whatsoever.

If your data is constant there is absolutely no reason to store it as String objects. It's constant. It should remain constant. Copying it into a String object means it's no longer constant and wastes many many resources.

  • fwiw, i find the String interface to result in much more semantic and readable code ex: response.endsWith(token) compared to gibberish-ladden alternatives. my $0.02 as a JS dev. – dandavis Oct 30 '17 at 0:23
  • Thank you. One Mord question: Would it be possible to use char arrays instead of String objects (as I don't really need their functionality). Would that (if possible) save space? – tr01 Oct 30 '17 at 15:28
  • Absolutely. If they are constants then you need to learn about PROGMEM, the F() macro, PSTR, etc. – Majenko Oct 30 '17 at 15:30
  • Would declaring the array with char[][16][5] also work? – tr01 Oct 30 '17 at 16:34
  • That would probably end up wasting as much memory. First decide what you want this array to do. Then relate that to what different types of array can do. Then code using that kind of array. – Majenko Oct 30 '17 at 16:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.