2

I wrote this test program:

void loop()
{
    digitalWrite(13,1);
    delay(300);
    digitalWrite(13,0);
    delay(300);
    void *a = malloc(10000000000000000000000000000000000000000);
}

Curiously, the LED keeps blinking and so it means the loops continues.

My question is how can it continue when it runs out of heap memory like that?

  • 3
    You do realize that your code never checks to see if malloc() actually succeeded, right? – Ignacio Vazquez-Abrams Dec 30 '15 at 4:13
  • you are right.. it probably failed on the first call. – ijklr Dec 30 '15 at 4:15
  • 2
    10000000000000000000000000000000000000000 doesn't fit in a 16-bit integer. I wouldn't be surprised if the compiler doesn't know what to do with such a large value, and just replaces it with a zero. Try it with more reasonable value. – Gerben Dec 30 '15 at 9:17
3

malloc() by itself generally doesn't crash a program. It attempts to allocate the requested amount of memory, and if it can it will. If it can't (there isn't enough memory available) then it won't allocate anything and will just return NULL.

By trying to allocate more memory than you have it will just fail every time and no memory will be allocated - thus you don't actually have a memory leak, so your program doesn't fail.

The main reason for crashing is a phenomenon called stack smashing where the memory area used by malloc() (known as the heap) and the memory area for the stack (used by local variables and for storing the contents of registers during function calls) collide with one another and one corrupts the other. For instance, if the return address of the current function in the stack is corrupted, when the function finishes it will return to the wrong memory location and who knows what may happen then? Wrong instructions will be executed for sure.

For instance, try this program out instead:

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

void loop() {
    char *a = (char *)malloc(10);
    if (a != NULL) {
        Serial.println("Allocated 10 bytes");
    } else {
        Serial.println("Allocation failed");
    }
}

If all goes well you should see lots of "Allocated 10 bytes" followed by some "Allocation failed". Since the memory is now full there is a chance that it may now crash as the stack and heap collide - in which case you would expect to see the "Allocation failed" messages stop.

  • The allocator has a "heap safety margin" of around 128 bytes so the crash is unlikely in this case. – Nick Gammon Jan 2 '16 at 20:22
0

Allocating memory doesn't really do much to it except for (typically) writing some bookkeeping information into its header - a portion the caller doesn't (isn't supposed to...) see. In particular, that bit of memory doesn't become unavailable for anything (other than further allocation).

Malloc maintains a buffer between the stack pointer location and the heap, from which it will not allocate. This tends to ( <--- note "weasel words") prevent a heap vs. stack collision

If the stack grows down into memory that was already allocated, the stack will over-write the data in some allocated block. It is impossible to say what effect that will have on further program operation without knowing a whole lot more about the program, and quite possibly, about the contents and timing of any data that has yet to be received.

If the heap grows upward into the stack, and program writes into that allocated block, it will be over-writing parts of it's own stack with, again, unpredictable (without a lot more information) results.

A simple test program that merely allocates lots of small blocks will have a good chance of running forever, or at least until the malloc() call returns a NULL pointer when it is out of memory to allocate. At that point, if the test program is checking for the NULL return, there is a good chance the program can print its message and end normally. But if the program blindly writes into the memory malloc() returns, and writes through the eventual NULL pointer, then low-memory will get corrupted. Low memory is typically the location of the interrupt vector table (and the Arduinos' AVR processors are no exception), some interrupt is likely to get vectored to somewhere other than its proper service routine, and abnormal program operation will result; most likely, a crash.

  • 1
    Writing to SRAM at address NULL (0x0000) on AVR actually does something interesting. It does not corrupt interrupt vector table. That is in the program memory (PROGMEM). avr-tutorials.com/general/avr-memory-map – Mikael Patel Dec 30 '15 at 16:37
  • Right - Harvard bites von Neumann again! :-) Thanks for the catch. – JRobert Dec 30 '15 at 23:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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