How to create and free dynamic arrays with Arduino

@6v6gt and @westfw : Maybe it is like with racing cars versus trucks :wink: Quick and lightweight but little load to carry or the other way around ...

So best practice seems to be to avoid dynamic memory allocation due to the hazard of memory fragmentation and crash between heap and stack.

If one still is keen to define arrays during runtime it might be a good idea to do this in a function with a local array but also check for available memory with some preserved space to avoid weird program behaviour. You may check the following sketch that I have tested empirically without encountering problems (maybe bad luck ...?!?) although I stressed it by recursive calls. It works of course ONLY with pod (plain old data like byte, int etc.). By using a while-loop instead of the standard main loop() you keep almost all variables in the local function thus utilizing the standard way of allocating and freeing data without the need to take care of that on your own:

// A const value that preserves bytes 
// to (hopefully) avoid running out of memory between heap and stack
// that might cause weird behaviour of the program
const byte c_reserve = 200;

// The depth of the recursive use of the function UseArray()
// Recursive calls are only used in this example to definetely 
// stress memory allocation and see what happens ...

int depth;

// The main function to create arrays in runtime
// Most lines are only useful for this example
// The core lines required are
// const byte c_reserved = 200;
//  void UseArray(byte Rows, byte Cols, byte reserve){
//      if (Cols*Rows*sizeof(WhatEverTypeOfPOD) + reserve >= freeMemory()){ return };
//      WhatEverTypeOfPOD MyA[Rows][Cols];
//      while(YouWantToLoop) {
//        // do Something in here
//        }
//     }
// With 
//  "WhatEverTypeOfPOD" may be any type of **plain old data**, such as byte, int, long, float
//  do not use this with types/objects that require constructor/destructor calls!
//  Cols, Rows = 1 or more
//  c_reserved = 200 or more (no gurantee, but worked fine in this stress test ...)

// forward declaration of getFreeMemory()
int getFreeMemory();

void UseArray(byte Rows, byte Cols, byte reserve){
  depth++;
  Serial.println("Depth = "+String(depth));
  if (Cols*Rows*sizeof(int) + reserve >= getFreeMemory()){
      Serial.print  ("Use Array ["+String(Rows)+"]["+String(Cols)+"] requires "+String(Cols*Rows*sizeof(int))+ " Bytes ");
      Serial.println("plus "+String(reserve)+" reserved bytes, but there are only "+String(getFreeMemory())+" Bytes available");
      return;
    }
  int MyA[Rows][Cols];
  static int Test = 1;
  Serial.println("Test = "+String(Test++));
  Serial.println("Use Array ["+String(Rows)+"]["+String(Cols)+"] with Free Memory = "+String(getFreeMemory()));
  
  for (int i= 0;i<Rows;i++) 
    for (int j= 0;j<Cols;j++) MyA[i][j] = (i+1)*100+j;
 
  for (int i= 0;i<Rows;i++){ 
    for (int j= 0;j<Cols;j++)
      Serial.print(String(MyA[i][j])+char(9));
    Serial.println();  
    }
 
   // In this test example you start recursive 
   // "dynamic" array creation with an 's' per Serial in the
   // following while-loop.
   // It will stop here again after all recursive function calls
   // have come back to the first call in the main loop()
   // where depth is reset to zero (see below)
   //
   boolean YouAreHappy = (depth == 1); 
   if (YouAreHappy) Serial.println("\nStart recursive calls per Serial input with 's' "); 
   while (YouAreHappy) {
    // Put your loop() content here
    if (Serial.available()){
      YouAreHappy = (Serial.read() != 's');
      }
    // End of loop() example  
    }
    UseArray(random(2,21),random(2,21),c_reserve);
    depth--;
    Serial.println("Returned to "+String(depth));
  }

void setup() {
  Serial.begin(115200);
  Serial.println("\n-----------------------------");
}

void loop() {
  Serial.println("Free Memory in loop() = "+String(getFreeMemory()));
  depth = 0;  
  UseArray(random(2,21),random(2,21),c_reserve);    
}

extern unsigned int __bss_end;
extern void *__brkval;

int getFreeMemory(){
    int free_memory;
    if((int)__brkval == 0) free_memory = ((int)&free_memory) - ((int)&__bss_end);
                      else free_memory = ((int)&free_memory) - ((int)__brkval);
    return free_memory;
}