[Heap Space] How to debug config assert ?

benoitdes wrote on Wednesday, July 09, 2014:

Hi everyone,

I use FreeRTOS 7.5.2 on a STM32F427 whith Coocox. I have a pretty huge program running on it including IOs (USB and Serial) and multiples tasks. I use heap_4.c.

I need a maximum of heap space for my program. I set configTOTAL_HEAP_SIZE to the maximum value corresponding to the remaining space allowed. Is this a problem ? How can i know the maximal heap space i can allocate ?

The second point is since i set the maximal amount of heap space, sometimes freeRTOS hangs on on one of these two asserts in vPortFree in heap_4.c :

configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
configASSERT( pxLink->pxNextFreeBlock == NULL );

Do you know what does it mean ? How can i know from where this call is performed before the assert ?

Sorry for my basic questions but i’m a bit lost in memory :).


edwards3 wrote on Wednesday, July 09, 2014:

heap_4 uses a static char array, so the linker know just how big it is. That means you can keep increasing configTOTAL_HEAP_SIZE until your application no longer links, then you can just wind it back a bit until you find the point where it does link - and that is the maximum size you can make it.

Blocks allocated from the heap include some meta data that the application never sees. If those asserts fail then something has written over the meta data, so something has written outside of the the allocated block. Basically it is a memory corruption.

benoitdes wrote on Thursday, July 10, 2014:

Thanks for your answer,

So configTotalHeapSize is easy to use. If some libraries uses a standard malloc instead of the pvPortMalloc i use, does it possibly lead to an overwrite of these pvPortMalloc metadatas ?
I have a very quick cyclic task (~2 ms) which is able to malloc and free a lot of times by cycle. Could this be the issue ?
More generaly how can i know what part of my code called this vPortFree before the Assert ?


rtel wrote on Thursday, July 10, 2014:

This depends on how the heap used by the standard malloc() function works. On many systems it does not use a defined size, but just grows until it hits something. In that case the technique described above to size the heap used by FreeRTOS is not helpful because it will prevent you from using the default C library’s malloc() all together.

If you are using both the default malloc() and FreeRTOS’s pvPortMalloc(), and you want to know how big the RTOS’s malloc can be, first you will need to find out how much space is needed by the default malloc() - then you can allow FreeRTOS to use whatever is left.

Alternatively you could use heap_3.c with FreeRTOS, then both malloc’s will use the same heap - but that might not be wise if you are rapidly allocating and freeing blocks (which is generally not a good idea anyway) because the default malloc() is likely to be slow, and if not slow, non deterministic. Consider allocating once, then just re-using the allocated blocks over and over rather than rapidly allocating and freeing.

The configASSERT() that is being triggered only tells you that something has overwritten the meta data between the block being allocated and the block being freed. It does not allow you to trap when the corruption actually occurred. To do that you may be able to use a watch point in your debugger though. If the corruption is repeatable, so you know which block is going to get corrupted, then break in the debugger when the block is allocated, set a break point on a data write to whichever byte in the metadata is being overwritten (you can see which memory the asserts are checking, xLink->xBlockSize or xLink->pxNextFreeBlock), start the program running again, and the debugger will break at the moment the data is overwritten. Whether that is possible or not depends your development environment.

Richard Barry.

benoitdes wrote on Thursday, July 10, 2014:


I took in consideration your hints and i finally found where the corruption came from. (of course from my code !).

Thanks a lot for your help,