Out of memory error


Well, in the good old times when coumputers were shipped with some 640 kBytes of RAM it was not unusual to read that message.
But where should a microcontroller display it?
And what should the user do in this case?

Actually, you know what to do, when your telephone, your DSL-router or other devices stop working: just restart them by disconnection power for a few seconds.

But what can a programmer do to prevent this to happen?

Well, there are internal variables giving you an info of how much is left of your SRAM:

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

Let's have a look on what's going to happen with recursive calls

For simplicity we choose to call setup() from inside the setup-function. (This program uses the above function.)

int n = 0;
 
void setup() {
  Serial.begin(9600);
  Serial.print(n++);
  Serial.print("   ");
  Serial.println(freeRam()); 
  delay(20);
  setup();
}

void loop() { }

When you upload this program and open a terminal window you will see each call of the setup function takes 6 bytes of memory.

And you will see that the recursion will terminate when there is not enough space for the stack any more .

It looks like a minimum of about hundred bytes of free SRAM is essential for a stable running system.
Of course, recursive calls are most unusual for microcontroller systems. But they simplify the way to exhaust the amount of free RAM.

What can you do to avoid out of memory errors?

Well, the compiler helps a lot to save memory. For instance, it will not help to reuse the same variable name for different purposes.
If a variable is not used any longer the compiler will feel free to allocate a new one at the same address.

Better have a look at your strings. They often are the cause for running out of memory.
Constant strings normally occupy space in your Flash RAM and in SRAM. To avoid this you can use the F() function introduced with Arduino 1.0.
See also the "Using Flash Memory for string storage" on http://playground.arduino.cc/Main/Printf

Other memory monsters will be big arrays of constants. Consider to swap them to a separate file. The also can remain in the Flash RAM.
To do this you need to include the <avr\pgmspace.h>-file to make use of the pgm_read_byte()-function.
See http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html for a complete list of all access functions.

Let's have a small example

fibo.ino
#define FLASH

#ifdef FLASH
   #include <avr\pgmspace.h>
#endif

#include "fibo.h"
 
void setup() {
  Serial.begin(9600);
  Serial.println(freeRam());
  for (int i = 0; i < 47; i++) {
    #ifdef FLASH
       Serial.println( pgm_read_dword(fibo + i));
    #else
       Serial.println(                fibo[i]);
    #endif
  }
}

void loop() { }
fibo.h
long fibo[] 

#ifdef FLASH
   PROGMEM
#endif

= {
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 
6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 
2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 
165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903 };

Our little project will have 3 tabs: the "main" program fibo.ino, the constants file fibo.h, and the freeRam function as show above.

If you do not define the FLASH directive the numerical data will be copied to the SRAM, and there is only 1649 bytes free.
(Declaring the array as const does not help.)
If you define the FLASH directive the data are read directly from the Flash memory instead, and as a result you get 1837 bytes free.
The difference is 47 times 4 bytes giving 188 bytes of extra memory.

Having shown this you also have a nice example of conditional compiling.

Of course, the Arduino could have calculated the Fibonacci numbers on its own and with less memory usage, but that was not the point.


contact: nji(at)gmx.de