So I understand that generally speaking, dynamic allocation should be avoided. My question isn't how or why, but what happens when you call a function that allocates memory?
On Windows or Linux, when a program allocates memory, a whole bunch of stuff happens, things like virtualisation and security related features that have no relevance to arduino, and the bit that I'm interested in, memory management:
There will be some code, that will look at the alignment and size requirements of the allocation request, look at the pool of memory it has access to, find a space big enough, make a note of the allocation (which also uses some amount of memory) and then return a pointer to the allocated space back to the calling function.
Is there a custom malloc implementation for each device, or does it come with the arduino toolchain (and does that mean Arduino has a different implementation from Teensy, or avr from sam?), or is there some magical default implementation supplied by the compiler? What kind of memory overhead is incurred with every allocation? How easy is it to override this functionality and implement your own (out of morbid curiosity or tendency towards masochistic endeavours)?
1 Answer 1
There are some hardware-specific abstractions (they mostly define the maximum memory available), but otherwise these are functions are implemented by the C/C++ runtime (on arduinos an implementation called "NewLib") and usually "just work". You might want to take a look at this question, where quite a bit of background is given on the SAM implementation of the hardware abstractions (because it's broken).
And yes, of course using malloc/free has some considerable overhead, which is one reason why it's not the recommended way of allocating memory on microcontrollers. But the logic behind it is mostly the same whether there's 2k of memory or 2G. And the memory model of modern microcontrollers (at least the 32 bit ones) is very similar to the one seen in 32 bit Windows or Linux apps.
malloc()
on AVR, see this page of the avr-libc documentation.malloc
:, largely neither. It's part of a libc implementation that typically covers many devices. Customizing the libc malloc in an algorithmic way usually means patching building libc yourself. There are a few Arduino specific stubs e.g. fornew
/delete
and moving the stack/heap break, but the bulk of what you're asking about (which is a lot) has really not much to do with Arduino.malloc()
implementations that I've looked at, including Due and ESP8266 ones use same the basic scheme described in EdgarBonet`s link and are tunable in roughly the same ways.