Who I am: I mostly have written in Java and have recently graduated college with a BS degree in Mathematics with a Minor in Computer Science. I have basic understanding of stack and pointers, but very little in garbage collection since JRE does this during runtime. Any assistance or corrections are welcome.
For the past week, I have been working on optimizing code and checking to insure that every line in the code is necessary for a specific application/ project to run successfully. In that pursuit, I have read several forum entries ranging from the 2011 to several weeks ago timeframe concerning memory management especially malloc and the dangers of the String object. Most of the entries are related to Arduino Uno or other Arduino microcontrollers with <=2K SRAM. However, I am working with an Arduino Mega 2560 R3 with 8K SRAM. My only concern is that for the project to run successfully for six months once placed into operation is that the heap doesn't get fragmented enough to have stack collision. The code below will be referenced throughout this entry.
//global variables that will be changed during operation
boolean data1 = true;
boolean data2 = true;
boolean data3 = true;
boolean data4 = true;
boolean data5 = true;
boolean data6 = true;
boolean data7 = true;
double data8 = 0.0;
double data9 = 0.0;
double data10 = 0.0;
double data11 = 0.0;
double data12 = 0.0;
double data13 = 0.0;
double data14 =0.0;
byte data15 =0;
byte data16 =0;
byte data17 =0;
byte data18 =0;
byte data19 =0;
byte data20 =0;
unsigned int data21 = 0;
unsigned int data22 = 0;
unsigned int data23 = 0;
unsigned int data24 = 0;
unsigned int data25 = 0;
unsigned long time = 0;
byte counter = 0;
boolean runOnce = true;
char cArray [140];
void setup()
{
Serial.begin(115200);
//pinMode will be called to setup the Digital pins to be either INPUT or OUTPUT
//setup any other sensors and begin the necessary libraries
time = millis();
}
void loop()
{
//several functions will be called to set data1, data2,...,data25
// by either ternary operator, analogRead(...), digitalRead(...), or a combination
if(abs(millis()-time)>=1000) // due to aarg comment: not need only to match difference formula
{
func1(); // sets data1
func2(); // sets data2
.
.
.
func25(); // sets data25
counter = ((counter+1)%60);
time=millis(); //this insures that data1, data2,...,data25 are set every second
}
// Now, cArray must be built using data1,data2,...,data25
if(counter==0 && runOnce)
{
set_cArray();
runOnce = false;
}
else if(counter==1 && !runOnce)
{
runOnce = true;
}
}
void set_cArray()
{
String s = String(data1) + "," + String(data2) + "," + String(data3) + "," +
String(data4) + "," + String(data5) + "," + String(data6) + "," +
String(data7) + "," + String(data8) + "," + String(data9) + "," +
String(data10) + "," + String(data11) + "," + String(data12) + "," +
String(data13) + "," + String(data14) + "," + String(data15) + "," +
String(data16) + "," + String(data17) + "," + String(data18) + "," +
String(data19) + "," + String(data20) + "," + String(data21) + "," +
String(data22) + "," + String(data23) + "," + String(data24) + "," +
String(data25);
Serial.print(F("Location of s: "));
Serial.println((int)&s);
s.toArray(cArray,s.length()+1);
// Question: on return is String object s deleted automatically off stack or heap?
}
My project uses Adafruit CC3000 WiFi shield with an SD card; thus, I am using Arduino 1.0.5-r2 IDE. set_cArray() in the code builds the cArray char array so that the cArray can be used by a write to SD function (NOT SHOWN) and to the Serial Window. In the near future, cArray will be sent using TCP to a client for monitoring and control. data1,data2,...,data25 are used by a LCD I2C module with a 20 char 4 line LCD, the write to LCD functions are not shown. All not shown code is due to not needed for this entry or questions to follow.
Now, to the nuts and bolts of this entry. In my reading, I have learned that SRAM is split into four parts: Global Variables, Heap, Free space and Stack. The issue that so many users have with String object, I gathered, is that the String object lives in Heap and when freeing Heap space the concatenation of bits/bytes can leave holes leading to heap fragmentation and eventual stack and heap collisions.
What I also have gathered is that functions store the local variables on the stack unless that local variable is created by a library (constructor) that builds the object in the heap. I am not sure about that last statement since I am pretty sure that each stack location is 32 bits 16 bits [verified by econjack] on the Mega; long enough to contain a pointer to a heap location. In set_cArray() function, the pointer to String object 's' stays the same when printed to the Serial Window since every time I call set_cArray the stack pointer is going to be in the same location due to function calls are always the same leading to stack usage is the same for the loop that calls set_cArray().
In the forum thread( Question about the life and memory space of a variable inside a function... - Programming Questions - Arduino Forum ), the user asked about the life of a local variable. However, if an object is stored on the heap with the pointer on the stack when the return pointer is called from the stack to the loop in the case of my code then the pointer is lost but the heap object remains, thus in set_cArray before '}' there should be a delete(s);? Or is the String object 's' entirely on the stack?
Before any comment of don't use String object, I am writing this code for a person with very basic basic understanding of code and he or she will have to update this code once this project goes operational. Thus, he or she will not understand C++ casting, which I have just started trying learn. The commonly suggested alternative to String object is sprintf() function. However, sprintf() on 25 differing data types would require up to 25 differing format specifiers since in real life the four data types are mixed up rather than the displayed code which has them grouped leading to a harder task for the code maintainer to manage. In addition, I am a Math major so Prove it don't just say it!
Thank you ahead of time for any comments or suggestions.
// Edited and attempted to clarify due to comments from PaulS, aarg and econjack.
Aug 20 added References:
Memory Heap: Memory heap - Programming Questions - Arduino Forum
Dangers of String object: String corrupts the heap and crashes - Suggestions for the Arduino Project - Arduino Forum
Memory Management/Optimizing Code: You know you have a memory problem when... | Memories of an Arduino | Adafruit Learning System