Yesterday, I wrote an article on Pointers and Dynamic Memory – Stack and Stack Overflow of Memory and I received good feedback about the article. More articles are requested by the fellow fans of cyberstorm.mu and I proposed to blog about “Heap”. As I discussed in the previous article, there are limitations to stack. We have to see exactly how stack overflow happens, that is, if our “calls” stack grows beyond the reserved memory of the stack, the program will consequently crash.
There are actually limitations to stack especially when the memory is set aside and it does not grow during runtime. Consequently, the application cannot request more memory. Note that the allocation and deallocation of memory on the stack are governed by a set of rules, that is, when a function is called, it is pushed onto the stack and when it finishes it is popped out of the stack. Hence, it is quite impossible to manipulate the aim of a variable when it is on the stack. Another limitation is when there is a large data type. For example. an array sets as a local variable where we need to know the size of the array at the compiling time! To overcome this problem of a large variable into the memory we have “heap”. Let’s now have some fun with heap?
Compared to size in Stack, an application’s heap is not fixed. Its size can vary during the whole lifetime of the application and there are no special rules applied during allocation and deallocation memory. Heap will grow its reserved memory as long as you do run out of memory in the whole system itself. That is why in the introduction article, the heap is described as a free pool of memory (Dynamic memory). To use Dynamic Memory there are four functions that need to be grasped, that is; Malloc, Calloc, realloc, and Free. I will get into more details of these terms in my next article.
Let’s see a C program to get into the heap structure:
#include<stdio.h> #include<stdlib.h> int main() { int a; int *p; p = (int*)malloc( sizeof (int)); *p = 10; free(p); p = (int*)malloc( sizeof (int)); *p = 20; }
- A variable “a” is declared from the main() method. It goes into the stack as explained in the diagram.
- We store the integer on the heap by calling the malloc() function. The line int *p; followed by p = (int*) malloc(sizeof (int)); will specify how much memory to allocate on the heap in terms of bytes. We just say “malloc please pass as argument the size of the integer..” and the program said “ok I give you a block of memory of 4 bytes” – 4 bytes is the size of an integer. Malloc will then return a pointer to the starting address of this block.
- Malloc will return a void pointer to the starting address of the block. Let’s say the starting address of the 4 bytes is 100.
- Since we have an integer p which is a local variable to main, this is allocated in the stack. Note that at this stage p stores the address 100 in the heap.
- We can store something in the heap by removing the reference pointer p towards the heap. This done by using pointer p and add some value – *p = 10;
- A pointer variable is also kept in the stack to point to the heap that is 100.
- At the line, p = (int*) malloc ( sizeof (int)); and *p=20 which is another call has been made to malloc and consequently one more byte of 4 bytes is allocated on the heap.
- Let’s say the address is 200 and the address called is stored in the variable p which will point to the address 200 from the stack. Note that the previous block of address 100 will still sit in the heap. Unnecessary consumptions of memory at this stage on the heap need to be clear out.
- This exactly where the line free (p); gets in to clear out. Number 3 in the heap block will be cleared out.
Anything allocated on the heap is not automatically deallocated when the functions get completed compared to the stack. It does not need to live the whole lifetime of the application. Programs which is coded with this fault can be used to explore vulnerabilities. We need to control anything that can be freed on the heap.