Search This Blog

Wednesday, August 27, 2014

Behaviour of malloc() and free() functions

malloc() is vastly used in real time programing due to its contiguous allocation
of memory. So that fragmentation can be minimized.
But malloc() allocation itself causes sever of exception for programmer without showing significance error sometime.

1) Boundary of malloc()
int *ptr = (int *)malloc(sizeof(int)*10);

Above syntex of memory allocation represents that we are allocating 40 bytes of
contiguous memory to integer pointer ptr. as an result a size of 40 bytes chunk
is reserverd in heap to provide data read/write for pointer ptr.

A programmer can write data upto 40 byte of boundary legally. But
case 1: Legal writing
   
    for(i = 0 ; i<10 ; i++)
    {
        ptr[i] = i;
    }
   
    This legal writing will not cause any error or fault. Allowed by compiler
   
case 2: Illegal writing
   
    for(i = 0; i < 20 ; i++)
    {
        ptr[i] = i;
    }
   
    This writing is illegal. because it writes beyond the boundary of malloc.
But is still allowed by compiler.

2) Role of free() function in exceptional cases

Free function frees the memory allocated by the malloc() or calloc() or
realloc() functions. And makes it reusable for further memory allocation.
In above example free() functions play a different role

case 1: Legal writing
   
    for(i = 0 ; i<10 ; i++)
    {
        ptr[i] = i;
    }
    free(ptr);

    In this case free() will simply free the memory without any exception.
case 2: Illegal writing
   
    for(i = 0; i<20 ; i++)
    {
        ptr[i] = i;
    }
    free(ptr);
   
    In this example free() function will lead to an exception i.e SIGABRT. This
happens because free() function detects the extra byte has been written beyond
the boundry.

Observation : Here one thing is need to observe that using malloc() is a good
programing practice but in some of cases programmer probably does not notice on
the writing limit of malloc() and eventually ends with SIGABRT. If programmer
debugging the code they will cross check the memory allocation and double free()
scenario. It seems all right because code looks healthy. this kind of logical
issue resolved by examine writing limitation of malloc().

3) Does free() function really frees the memory
To better understand free() function once need to know how malloc() allocates
the memory. malloc() function passes the size of memory to allocate to the
system where kernel allocates required block for data. but kernel adds one
additional block of information before each allocation. That block called
meta-data and it contains mainly information about size of data that is
allocated free flag(0 = used, 1= free) and address of next meta-data.
    Whenever free() functions tries to free a memory block it Enables the free
flag in meta-data structure. That means block of specific size is freed and
available for next time of allocation. Here the question is what happen next to
the data block can be easily understood by following examples.
case 1:
    int *ptr = (int *)malloc(sizeof(int)*5);
    int i = 0;
    for(i = 0; i<5 ; i++)
    {
        ptr[i] = i;
    }
    for(i = 0; i<5 ; i++)
    {
        printf("%d\t",ptr[i]);
    }
    printf("\n");
    free(ptr);
    for(i = 0; i<5 ; i++)
    {
        printf("%d\t",ptr[i]);
    }
    Output -
   
    0    1    2    3    4   
    0    0    2    3    4
[NOTE : This out may vary compiler wise]   
    free() function does not affect the data block. It simply makes it
available for next allocation.

This happens because of enabling free flag in meta-data. But what does it
really means enabling and disabling a flag. Whenever free() called to free a
dynamic memory it checks the meta data status and size of memory allocation.

Memory allocation happens by two mechanism in kernal space. if malloc is
allocating memory less then 135168 bytes ( approx figure, may vary), then it
uses sbrk() function to allocate memory. This allocated memory does not free
completely. programmer should assign NULL to the pointer after freeing it.
though this type of memory boundary is not well defined so sometime it is
observed that program can write beyond of allocation without showing any fault.
free happens only enabling the free flags in meta data.
But if memory to be allocated accedes 135168 bytes , system uses mmap() to
allocate memory. This kind of memory allocation very constrain to its boundary.
user can not write of use these memory after freeing it. because munmap is used
to free  these memory.
To check memory allocation region by malloc we have one command in gdb.

(gdb) print or p malloc_stats(<address or pointer variable >)

output:
(gdb) p malloc_stats (0x7ffff7a9ea70)
Arena 0:
system bytes     =     135168
in use bytes     =          0
Total (incl. mmap):
system bytes     =     135168
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0
$2 = -136494720
(gdb)

Here we can see there are two regions defined in this out put 1. System Bytes
2. mmap regions