AnsweredAssumed Answered

Heap allocation/checking in Redlib

Question asked by LPCware Support on Mar 31, 2016

By default, the heap used by Redlib's malloc() family of routines grows upwards from the end of the user data in RAM up towards the stack - a "one region memory model".

 

When a new block of memory is requested, the memory allocation code will make a call to the following function to check for heap overflow:

 

unsigned __check_heap_overflow (void * new_end_of_heap)

 

This should return:

  • 1 - If heap will overflow
  • 0 - If heap still OK

If 1 is returned, malloc() will set errno to ENOMEM and return a null pointer to the caller

 

Default implementation - LPCXpresso 7.30 and later

 

In LPCXpresso 7.3.0 and later, the default version of __check_heap_overflow() carries out no checking unless the symbol "_pvHeapLimit" has been created in your linker script, to mark the end location of the heap. To modify the location of the heap and if, required, check for overflow:

 

  1. Modify the setting of the "_pvHeapStart" variable created within the linker script, which is used to mark the starting location for the heap.
  2. Ensure that "_pvHeapLimit" variable is also created by the linker script, to mark the end location of the heap.

 

For more details of modifying linker scripts, see the FAQ "Linker script templates". It is also possible to set the end location of the heap without modifying linker scripts/templates. This can be done by defining "_pvHeapLimit" on the linker command line. This can be done by adding an appropriate option to the MCU Linker - Miscellaneous - Other Options box in Project Properties.For example:

 

  • --defsym=_pvHeapLimit=_pvHeapStart+0x400

 

will set the end location of the heap to 1KB beyond the start of the heap, and

 

  • --defsym=_pvHeapLimit=0x10004000

 

will set the end location of the heap to the absolute address specified.Note that the "one region memory model check" used by earlier versions of LPCXpresso IDE has now been disabled by default. This has been done as the assumptions it makes about memory layout are quite simplistic, and can 'broken' in many real applications, for example where an RTOS is being used which provides a separate stack for each task.

 

Start of heap setting in LPCXpresso 7.4.0 and later

 

Starting in LPCXpresso 7.4.0, it is also possible to modify the start address of the heap without modifying linker scripts/templates.  This can be done by defining the symbol "__user_heap_base" on the linker command line. This can be done by adding an appropriate option to the MCU Linker - Miscellaneous - Other Options box in Project Properties, as per the heap limit above. This value will then be assigned to the symbol  "_pvHeapStart" within the linker script. Note that if you are using a linker script template, then you will need to update to the latest template version provided in the Wizards subdirectory of your installation.

 

Default implementation - LPCXpresso 7.20 and earlier

 

LPCXpresso 7.2.0 and earlier carried out a more extensive check based on the assumption  of a one region memory model. The __check_heap_overflow() would:

  1. First of all checks that the start of the heap is below the stack
    • In this case a default 1 region model is assumed, such that the heap is growing up towards the stack
    • It then checks whether the new end of heap value will collide with the heap
    • If it does, then the function returns, with value 1 indicating overflow
  2. It now checks whether the end of heap is defined, via the variable "_pvHeapLimit", which will typically be set in the linker script
    • If it is, then it checks to see if the new end of heap value will exceed the limit
    • If it does, then the function returns, with value 1 indicating overflow
  3. Otherwise the function returns with value 0, indicating it is safe to allocate the heap.

It is possible for the user to modify heap setup such that the heap is placed in different region of memory to the stack (a "two region memory model"). To do this, you will need to...

  1. Modify the setting of the "_pvHeapStart" variable created within the managed linker script, which is used to mark the starting location for the heap.
  2. Ensure that "_pvHeapLimit" variable is also created by the linker script, to mark the end location of the heap.

Then as long as "_pvHeapStart" is above the stack in memory, the default __check_heap_overflow() will continue to function correctly. Alternatively you can provide your own implementation of __check_heap_overflow(), to replace the default one pulled in from Redlib.

 

Example implementation : __check_heap_overflow()

 

An example version of this function, which implements the default 7.30 behaviour detailed above is attached to this FAQ for reference. This can also be built so that it provides similar behaviour provided by the version included in LPCXpresso 7.2.0 and earlier - by setting the define ONE_REGION_MODEL_HEAPCHECK.

 

As long as you provide your own implementation inside your main application project (rather than in another library project), then the one from your application project will be found first - and hence the Redlib library version will not get pulled in. If you want to check that your own implementation has been picked up, then you can examine the map file generated by the linker.

 

Current end of heap

 

Redlib uses the global variable "__end_of_heap" to keep track of the end of the heap. Be aware though that this does not necessarily detail the maximum extent of the heap, only its current extent.

Outcomes