Problem
In C, dynamic memory is allocated with the malloc library function, while C++ uses the new operator. On bare-metal systems this is usually fine, but under an RTOS you must consider resource protection. For example, if multiple tasks call malloc concurrently without disabling interrupts or using a mutex, the same block could be allocated to two tasks and global allocator state can be corrupted.
Therefore, when using malloc under an RTOS (it should not be used in interrupts), you must protect it. Common RTOSes such as FreeRTOS and RT-Thread provide their own dynamic memory implementations; it is recommended to use the OS-provided allocation functions for better safety.
When you must maintain legacy code
Sometimes a legacy project heavily uses malloc and new. Replacing every call can be laborious and error-prone for large codebases. A practical approach is to redirect the functions while keeping their names, similar to using weak symbols to override standard functions.
Simply add the following code in a C file:
#include "stdlib.h" #if defined(__CC_ARM) void *$Super$$malloc(size_t); void *$Sub$$malloc(size_t size){ // mutex_lock() void *addr = $Super$$malloc(size); // mutex_unlock() return addr; } void $Super$$free(void *); void $Sub$$free(void *addr){ // mutex_lock() $Super$$free(addr); // mutex_unlock() } #endif
Note: this redirection mechanism is available in the MDK environment. With this approach, upper-layer code does not need modification: all calls to malloc and free will invoke the above sub functions, allowing you to add mutexes or tracing prints for debugging.
C++ version
C++ supports overriding global new and delete operators. Note that many STL containers are not thread-safe, for example push_back(), so use with caution.
#include <cstdlib> void *operator new(size_t size) throw(std::bad_alloc){ void *addr = malloc(size); return addr; } void operator delete(void *addr) throw(){ free(addr); } void *operator new[](size_t size) throw(std::bad_alloc){ void *addr = malloc(size); return addr; } void operator delete[](void *addr) throw(){ free(addr); } void *operator new(std::size_t size, const std::nothrow_t & nothrow){ void *addr = malloc(size); return addr; } void *operator new[](std::size_t size, const std::nothrow_t & nothrow){ void *addr = malloc(size); return addr; }
Hope this is helpful.
ALLPCB