Using malloc() and free() with 2D arrays in Arduino C

I’m working on a project that involves uploading and storing a very compressed image file on an Arduino MKR1000 as a 2D array of bytes. I noticed that after uploading a couple images it stopped working, which I’m fairly certain is because I’m simply running out of memory. I decided to do some research and experimentation, and started reading about malloc() and free() commands.

My program to demonstrates how I can create a 1 dimensional dynamic array, write data to it and resize it, works perfectly fine:

byte* data = (byte*)malloc(100);
int number = 0;

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

void loop() {
  number++;
  data = new byte[100];
  for (int i = 0; i < 100; i++) {
    data[i] = 1;
  }
  free(data);
  
  data = new byte[50];
  for (int i = 0; i < 50; i++) {
    data[i] = 1;
  }
  free(data);
  Serial.println(number);

}

This code outputs how many loops it has preformed on the Serial monitor, reaching 50000 quite quickly

However when I tried to do this with a 2D array, I couldn’t figure out how to get it to work. I have a number of different attempts, this was one was the closest I got:

byte **data;
int x = 0;
int i = 0;
int number = 0;
void setup() {
  Serial.begin(9600);
  while (!Serial) {
    Serial.println("working...");
  }
  data = (byte**)(malloc(100*sizeof(byte)));
}

void loop() {
  number++;

  data = new byte*[5];
  for (x = 0; x < 5; x++) {
    data[x] = new byte[5];
  }
  free(data);
  data = new byte*[5];
  for (x = 0; x < 5; x++) {
    free(data[x]);
    data[x] = new byte[5];
    for (i =0; i < 5; i++) {
      data[x][i] = 1;
    }
  }
  free(data);
  for (x = 0; x < 5; x++) {
    free(data[x]);
  }

  data = new byte*[10];
  for (x = 0; x < 10; x++) {
    data[x] = new byte[5];
  }
  free(data);
  data = new byte*[10];
  for (x = 0; x < 10; x++) {
    free(data[x]);
    data[x] = new byte[5];
    for (i = 0; i < 5; i++) {
      data[x][i] = 1;
    }
  }
  free(data);
  for (x = 0; x < 10; x++) {
    free(data[x]);
  }
  
  Serial.println(number);
}

Rather than counting continually it just gets to 3 and stops. In some other experiments I’ve gotten around 180, sometimes 1800, but they always stop once it either runs out of ram or allocated ram.

I’m sure I’m doing something seriously wrong with how I’m freeing and reallocating memory, however I have no idea what I should change to get it all to work. Can someone show me an example code of how to use malloc() and free() to create a 2D array that can change size?

byte **data;

"byte **" does NOT define a two-dimensional array. Rather, it defines an array of pointers to one-dimensional arrays. A pointer to a two-dimensional array of byte is still just "byte *" Alas, I'm not quite sure how to access that via double indices...

I see two likely problems. First, you're not using malloc, you're doing a "new". Then you use free(), when you should be doing a delete. Either use malloc and free, or new and delete. You don't get the mix and match as they don't necessarily do exactly the same thing. Personally, being an old c guy, I just use malloc and free:

int rowlen = 10;
int nrows = 5;
byte *someArray = (byte *)malloc (rowlen * nrows);
...
byte x = someArray[x][y];
...
free(someArray);

Regards, Ray L.

Ok I seem to have gotten it to work with “new” and “delete”. Thanks a bunch! Here’s my code in case anyone’s curious.

byte **data;
int x = 0;
int i = 0;
int number = 0;
void setup() {
  Serial.begin(9600);
  while (!Serial) {
    Serial.println("working...");
  }
 
}

void loop() {
  number++;
  data = new byte*[5];
  for (x = 0; x < 5; x++) {
    data[x] = new byte[5];
  }
  for (x = 0; x < 5; x++) {
    for (i =0; i < 5; i++) {
      data[x][i] = 1;
    }
  }
  for (x = 0; x < 5; x++) {
    delete(data[x]);
  }
  delete(data);

  data = new byte*[10];
  for (x = 0; x < 10; x++) {
    data[x] = new byte[5];
  }
  for (x = 0; x < 10; x++) {
    for (i =0; i < 5; i++) {
      data[x][i] = 1;
    }
  }
  for (x = 0; x < 10; x++) {
    delete(data[x]);
  }
  delete(data);

  
  Serial.println(number);
}

If you are deleting arrays, you need to use the array version of delete.

Incorrect:

[nobbc]delete(data[x]);
delete(data);[/nobbc]

Correct:

[nobbc]delete [] data[x];
delete [] data;[/nobbc]