I am debugging a bare-metal project on Kinetis TWRK70M120 using Cross ARM GCC toolchain. (Kinetis Design Studio)
I have one question:
Why malloc() doesn't return NULL pointer when it overruns the heap size?
How is that possible?
I would not expect it, but after analyzing different situations it showed up, that malloc() returns NULL pointer only if there is not enough space neither in HEAP nor in STACK. I found this question on StackOverflow forum:
When does malloc return NULL in a bare-metal environment?
They are talking about the HEAP and STACK collision, what could be related with this problem. Although, i am not sure if we can talk about collision even if both (STACK and HEAP) address ranges are managed correctly (it seems to me). For example if i define an local array with 10 integers it will occupy cca 40-48 bytes at the top of the STACK. It means that this part of stack is not available for dynamic allocation and malloc() returns NULL only if you try to allocate address space bigger than cca HEAP+STACK-48bytes. In my project 0x400 + 0x500 - 48bytes(mentioned array) - other local variables. I am really not sure if this is common behavior or i just don't understand correctly to malloc() function.
Here is my code which i used for testing the malloc function.
HEAP size = 0x20000400
HEAP size = 0x20000500
Here is my code which i used for testing the malloc function.
#include "MK70F12.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
extern uint32_t __HeapBase;
extern uint32_t __HeapLimit;
extern uint32_t __StackTop;
extern uint32_t __StackLimit;
//MY TEST
static int j=0, k=0, i=0; //Global variables
int main(void)
{
//For testing purposes I defined STACK = 0x0x00000500 (cca 1280bytes) and
//HEAP = 0x0x00000400 (cca 1024bytes) what means that
//I have approximately (theoretically) 2304 bytes available.
/* Write your code here */
void* pHeapBase = ((void*)&__HeapBase);
void* pHeapLimit= ((void*)&__HeapLimit);
void* pStackTop = ((void*)&__StackTop);
void* pStackLimit= ((void*)&__StackLimit);
//---------------------------------------------------------------------------------------------------------
char* pMalloc_data1=(char*)malloc(1200*sizeof(char)); //Dynamically allocated array which size is bigger
//than the HEAP size (beginning address in HEAP space).
//It seems, when it overruns the heap size it doesn't
//return NULL, but it continues growing into the stack.
//Malloc returns NULL pointer only if there is
//no space available neither in the HEAP nor in the STACK.
if (pMalloc_data1==NULL)
{
return(1); //Allocation failed
}
for(j=0;j<1200;j++)
{
*(pMalloc_data1+j)='a'; //just some initialization with character
//memory filled with 1200 chars
//address range 0x200000a8 - 0x20000559(0x20000558?)
}
//---------------------------------------------------------------------------------------------------------
int *pMalloc_data2 = (int*)malloc(10*sizeof(int)); //Dynamically allocated array
//(beginning address in STACK space)!!!.
//Malloc returns NULL pointer only if there is
//no space available in the STACK (HEAP is already full).
if (pMalloc_data2==NULL)
{
return(1);
}
for(i=0;i<10;i++)
{
*(pMalloc_data2+i)=i+4000; //memory filled with 200 integers
//address range 0x20000560 - (theoretically)0x20000588 (0x20000590?)
}
int array[10] = {10,15,78,62,80,6528,8,58,64,984}; //Local static array => in STACK
//For this array is space in STACK reserved
//at the beginning of the program
free(pMalloc_data1);
free(pMalloc_data2);
for(;;)
{
k++;
}
return 0;
}