0

according to the official documentation of the Arduino, the SRAM memory (which is allocated for the local variables) should be automatically released after calling any function. For example, I have a function memory_allocate_test2, which declares a large char array and this function is called in the loop(). I expect, that every time, after the function memory_allocate_test2 is executed, the SRAM memory that I allocated for the local variables within that function should be freed or released. However, it is not working like that. When I call that function in a loop() the microcontroller hangs and stops working because it runs out of the available SRAM memory. Let me provide an example code:

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only - development mode. It has to be removed when releasing to live!!!
  }
}

void loop() {
  delay(2000);
  memory_allocate_test2();
}

void memory_allocate_test2() {
  Serial.println("memory_allocate_test2 STARTING ");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  Serial.println("Allocating the memory for the MKR: ");
  char* memory_usage_test = new char[2000];
  Serial.println("Allocated memory!");
  display_freeram();
  Serial.println("------------------------------------------------------------");
}

extern "C" char* sbrk(int incr);

void display_freeram(){
  Serial.print(F("- SRAM left: "));
  Serial.println(freeRam());
}

int freeRam() {
  char top;
  return &top - reinterpret_cast<char*>(sbrk(0));
}

why it doesn't work as it states in the documentation? what I'm doing wrong? why the SRAM memory is not released each time after the memory_allocate_test2 function execution?

https://www.seeedstudio.com/blog/2021/04/26/managing-arduino-memory-flash-sram-eeprom/

when I execute that program, here is what happens:

memory_allocate_test2 STARTING

  • SRAM left: 7163

Allocating the memory for the MKR: Allocated memory!

  • SRAM left: 5155

memory_allocate_test2 STARTING

  • SRAM left: 5155

Allocating the memory for the MKR: Allocated memory!

  • SRAM left: 3147

memory_allocate_test2 STARTING

  • SRAM left: 3147

Allocating the memory for the MKR: Allocated memory!

  • SRAM left: 1139

memory_allocate_test2 STARTING

  • SRAM left: 1139

Allocating the memory for the MKR: Allocated memory!

  • SRAM left: -869

memory_allocate_test2 STARTING

  • SRAM left: -869

Allocating the memory for the MKR:

at that point the device just hangs and stops working. That's not what I expect!

since the functionality differs for each board and microcontroller, here are my specs: the board name is "Arduino® MKR WiFi 1010", the microcontroller name is "SAMD21 Cortex®-M0+ 32bit low power ARM MCU"

5
  • 2
    what documentation?
    – Juraj
    Commented Oct 2, 2023 at 4:54
  • 1
    it's not the microcontroller that controls the allocation and the release of the memory ... it is the program that does that ... also, there is no such thing as an Arduino microcontroller
    – jsotola
    Commented Oct 2, 2023 at 4:58
  • 1
    also asked at forum.arduino.cc/t/arduino-mkr-wifi-1010-memory-management/…
    – Juraj
    Commented Oct 2, 2023 at 4:59
  • @Juraj the only documentation article about the memory structure and management of the MKR WiFi 1010 that is I have found is provided in the question above. Could you please point me to the official documentation, because I saw so many different articles and examples, which often say a different thing. Commented Oct 2, 2023 at 7:08
  • @jsotola right, sorry for my mistake, the board name is "Arduino® MKR WiFi 1010", the microcontroller name is "SAMD21 Cortex®-M0+ 32bit low power ARM MCU". I have updated the question content. Commented Oct 2, 2023 at 7:11

1 Answer 1

1

You are mixing two different ways of memory allocation.

The automatic memory allocation and release you cite works with defined local variables. These variables are allocated on the stack. At the end of their scope, their memory is released. To mimic your example:

void memory_allocate_test3() {
  Serial.println("memory_allocate_test3 STARTING ");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  Serial.println("Allocating the memory for the MKR: ");
  char memory_usage_test[2000] = "Some content...";
  Serial.println("Allocated memory!");
  display_freeram();
  Serial.println("------------------------------------------------------------");
}

But what you use is heap-allocated memory because of the new operator. This kind of allocation is under complete responsibility of the programmer, this is you. Since you only allocate and never release, each loop reduces the remaining RAM. Use delete (actually delete[]) to release:

void memory_allocate_test2() {
  Serial.println("memory_allocate_test2 STARTING ");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  Serial.println("Allocating the memory for the MKR: ");
  char* memory_usage_test = new char[2000];
  Serial.println("Allocated memory!");
  display_freeram();
  Serial.println("------------------------------------------------------------");
  delete[] memory_usage_test;
}

Beware: There are different allocation methods, malloc/calloc/alloca/free and new/delete. The former method uses functions of the C standard library, the latter method uses keywords of C++.

The pointers returned by the different methods are not compatible. You cannot release memory by free that you allocated by new. The same holds true for delete/malloc.

However, you can use both methods in the same program.

Please learn about memory allocation before attempting to use it. C and C++ are error-prone to the unsuspecting user.

As a side note, C and C++ are different languages, even though you can build a mixed program.

2
  • is it same as calling free(memory_usage_test)? I saw somewhere during the research that it is not recommended to use the malloc(...) and free(...) functions for the MKR WiFi 1010, do you know something about that? This question is raised because I'm using some classes in my code, that internally use the malloc(...) and free(...) functions. Commented Oct 2, 2023 at 7:27
  • See the extended answer. Commented Oct 2, 2023 at 8:07

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