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!
Hello,
In some projects I added the source files for malloc(), free() to the project instead of using the library-functions because that implementation of free() attempts to consolidate small blocks into the largest block possible. Therefor the memory does not get fragmented. For debug purpose I also count number of allocated memory blocks and total size of allocated memory. This helps finding memory leaks.
When I use malloc(), free() from the library (µVision V5.14), does the memory get fragmented? Does it make a difference whether I use the Keil RTOS or not?
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.