Hi, I'm using arm cortex, KEIL, FreeRTOS. The problem I met is: after many times of running the following malloc function, the heap was used out, couldn't allocat 1KB space any more.
char Str = (char )myMalloc(strLen); // strLen is a variable, value between 0 and 1024 if(Str != NULL){ ...... myFree(Str); }
Here are the definitions of myMalloc and myFree:
void myMalloc( size_t xWantedSize ) { void pvReturn;
pvReturn = NULL; if(xWantedSize) { vTaskSuspendAll(); pvReturn = malloc( xWantedSize ); xTaskResumeAll(); } return pvReturn; } void myFree( void *pv ) { if( pv ){ vTaskSuspendAll(); free( pv ); xTaskResumeAll(); } }
After the parameter strLen was changed to a fixed value, the problem was gone. Why variable length malloc doesn't work properly? Anything wrong in functions above?
Any help will be appreciated.
Thank you!
It's normal that implementations of free() tries to merge free blocks, unless the malloc()/free() implementation runs a system with pools of different-sized blocks.
Fragmentation normally happens when the malloc()/free() call sequence doesn't look like the use of a stack where the blocks always gets released in reversed order of the allocation.
If malloc()/free() happens in "random" order with different-sized blocks, then you may start with a big block
................
Then allocate block A, followed by B:
AAABB...........
Then you release A and allocate two larger blocks C and D:
...BBCCCCCDDDDD.
Then you release C
...BB....DDDD.
As you can see, you can quickly get situations where some long-living (but potentially very small) blocks can split the free space into many smaller regions that each is too small for the allocation you need to perform.
That is why malloc()/free() are so problematic in long-living embedded software in devices where you need to run with quite high memory utilization.
If we assume that malloc() internally needs 16 bytes for book keeping, then the fragmentation issue can be reduced a lot if the program only allocates blocks that are 2^n - 16 byte large and with the minimum allowed size set quite high.
So the heap ends up splitting the memory into 512-byte, 1024-byte, 2048-byte, 4096-byte blocks.
Keil has taken this concept even further with their box allocator, where you create arrays of fixed-sized blocks that you allocate from.