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?
1 Answer 1
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– dandavis2017年10月30日 00:23:58 +00:00Commented Oct 30, 2017 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– tr012017年10月30日 15:28:57 +00:00Commented Oct 30, 2017 at 15:28
-
Absolutely. If they are constants then you need to learn about PROGMEM, the F() macro, PSTR, etc.Majenko– Majenko2017年10月30日 15:30:41 +00:00Commented Oct 30, 2017 at 15:30
-
Would declaring the array with
char[][16][5]
also work?tr01– tr012017年10月30日 16:34:17 +00:00Commented Oct 30, 2017 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– Majenko2017年10月30日 16:49:32 +00:00Commented Oct 30, 2017 at 16:49
Explore related questions
See similar questions with these tags.
String
instances are more than just their characters.Serial.print
is usually lost (or garbage). Usual idiom to put awhile (!Serial);
insetup
, before printing anything. Pay attention to the semi-colon.