Open In App

Static and Dynamic Memory Allocation in C

Last Updated : 23 Apr, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Memory is divided into smaller addressable units called bytes. Assume that these are small boxes as bytes. Each byte has its own address as per the below table.For example: 0, 1, 2, 3, 4, 5, 6, etc.

Memory

How program uses memory?

The Memory is divided into three sections. 

  • Heap Memory: It is a part of the main memory. It is unorganized and treated as a resource when you require the use of it if not release. Heap memory can’t be used directly with the help of a pointer.
  • Stack Memory: It stores temporary variables created by a function. In stack, variables are declared, stored, and initialized during runtime. It follows the First in last out method that means whatever element is going to store last is going to delete first when it’s not in use.
  • Code Section: Whenever the program is executed it will be brought into the main memory. This program will get stored under the code section. Based upon the program it will decide whether to utilize the stack or heap sections.

Below is the image to illustrate how the program uses memory:

How program uses memory

Static Memory Allocation

In static memory allocation whenever the program executes it fixes the size that the program is going to take, and it can’t be changed further. So, the exact memory requirements must be known before. Allocation and deallocation of memory will be done by the compiler automatically.  When everything is done at compile time (or) before run time, it is called static memory allocation.

Key Features:

  • Allocation and deallocation are done by the compiler.
  • It uses a data structures stack for static memory allocation.
  • Variables get allocated permanently.
  • No reusability.
  • Execution is faster than dynamic memory allocation.
  • Memory is allocated before runtime.
  • It is less efficient.

For Example:

C++




// C++ program to illustrate the
// concept of memory allocation
#include <iostream>
using namespace std;
  
// Driver Code
void main()
{
    int a; // 2 bytes
    long b; // 4 bytes
}


Explanation:

  • The above piece of code declared 2 variables. Here the assumption is that int takes 2 bytes and long takes 4 bytes of memory. How much memory is taken by variables is again depending upon the compiler.
  • These variables will be stored in the stack section. For every function in the program it will take some part of the stack section it is known as the Activation record (or) stack frame and it will be deleted by the compiler when it is not in use.
  • Below is the image to illustrate the same:

Static memory allocation

Below is the C program to illustrate the Static Memory Allocation:

C




// C program to implement
// static memory allocation
#include <stdio.h>
#include <stdlib.h>
  
// Driver code
int main()
{
    int size;
    printf("Enter limit of the text: \n");
    scanf("%d", &size);
    char str[size];
    printf("Enter some text: \n");
    scanf(" ");
    gets(str);
    printf("Inputted text is: %s\n", str);
    return 0;
}


Input:

Output#1

Output:

Output#2

Advantages:

  • Simple usage.
  • Allocation and deallocation are done by the compiler.
  • Efficient execution time.
  • It uses stack data structures.

Disadvantages:

  • Memory wastage problem.
  • Exact memory requirements must be known.
  • Memory can’t be resized once after initialization.

Dynamic Memory Allocation

In Dynamic memory allocation size initialization and allocation are done by the programmer. It is managed and served with pointers that point to the newly allocated memory space in an area which we call the heap. Heap memory is unorganized and it is treated as a resource when you require the use of it if not release it.  When everything is done during run time or execution time it is known as Dynamic memory allocation.

Key Features:

  • Dynamic allocated at runtime
  • We can also reallocate memory size if needed.
  • Dynamic Allocation is done at run time.
  • No memory wastage

There are some functions available in the stdlib.h header which will help to allocate memory dynamically.

  • malloc(): The simplest function that allocates memory at runtime is called malloc(). There is a need to specify the number of bytes of memory that are required to be allocated as the argument returns the address of the first byte of memory that is allocated because you get an address returned, a pointer is the only place to put it.

Syntax:

int *p = (int*)malloc(No of values*size(int));

The argument to malloc() above clearly indicates that sufficient bytes for accommodating the number of values of type int should be made available. Also notice the cast (int*), which converts the address returned by the function to the type pointer to int. malloc() function returns a pointer with the value NULL.

  • calloc(): The calloc() function offers a couple of advantages over malloc(). It allocates memory as a number of elements of a given size. It initializes the memory that is allocated so that all bytes are zero. calloc() function requires two argument values: 
    • The number of data items for which space is required.
    • Size of each data item.

It is very similar to using malloc() but the big plus is that you know the memory area will be initialized to zero.

Syntax: 

int *p = (int*)calloc(Number of data items, sizeof(int));

  • realloc(): The realloc() function enables you to reuse or extend the memory that you previously allocated using malloc() or calloc(). A pointer containing an address that was previously returned by a call to malloc(), calloc(). The size in bytes of the new memory that needs to be allocated. It allocates the memory specified by the second argument and transfers the contents of the previously allocated memory referenced by the pointer passed as the first argument to the newly allocated memory.

Syntax:

int *np = (type cast) realloc (previous pointer type, new number of elements * sizeof(int));

  • . free(): When memory is allocated dynamically it should always be released when it is no longer required. Memory allocated on the heap will be automatically released when the program ends but is always better to explicitly release the memory when done with it, even if it’s just before exiting from the program. A memory leak occurs memory is allocated dynamically and reference to it is not retained, due to which unable to release the memory.

Syntax:

free(pointer);

For Example:

C




// C program to illustrate the concept
// of memory allocation
#include <iostream>
using namespace std;
  
// Driver Code
void main()
{
    int* p; // 2 bytes
    P = (int*)malloc(5 * sizeof(int));
}


Examples: 

  • In the above piece of code, a pointer p is declared. Assume that pointer p will take 2 bytes of memory and again it depends upon the compiler.
  • This pointer will store in the stack section and will point to the array address of the first index which is allocated in the heap. Heap memory cannot be used directly but with the help of the pointer, it can be accessed.

Free

  • When the program is not in use, the memory should be deallocated. Otherwise, it will cause a memory leak.

Memory leak

  • After deallocating the memory allocated in the heap. Below is the image to illustrate the main memory after deallocation.

Deallocating heap memory

Below is the C program to illustrate the Dynamic Memory Allocation:

C




// C program to illustrate the above
// concepts of memory allocation
#include <stdio.h>
#include <stdlib.h>
  
// Driver Code
int main()
{
    int size, resize;
    char* str = NULL;
    printf("Enter limit of the "
           "text: \n");
    scanf("%d", &size);
  
    str = (char*)malloc(size * sizeof(char));
  
    // If str is not NULL
    if (str != NULL) {
        printf("Enter some text: \n");
        scanf(" ");
        gets(str);
        printf("Inputted text by allocating"
               "memory using malloc() is: "
               "%s\n",
               str);
    }
  
    // Free the memory
    free(str);
    str = (char*)calloc(50, sizeof(char));
  
    // If str is not NULL
    if (str != NULL) {
        printf("Enter some text: \n");
        scanf(" ");
        gets(str);
        printf("Inputted text by allocating "
               "memory using calloc() is: "
               "%s\n",
               str);
    }
  
    printf("Enter the new size: \n");
    scanf("%d", &resize);
    str = (char*)realloc(str, resize * sizeof(char));
  
    printf("Memory is successfully "
           "reallocated by using "
           "realloc() \n");
  
    // If str is not NULL
    if (str != NULL) {
        printf("Enter some text: \n");
        scanf(" ");
        gets(str);
        printf("Inputted text by reallocating"
               " memory using realloc()is: "
               "%s\n",
               str);
    }
  
    // Free the memory
    free(str);
    str = NULL;
  
    return 0;
}


Input:

Output#1

Output:

Output#2

Advantages:

  • Dynamic Allocation is done at run time.
  • We can allocate (create) additional storage whenever we need them.
  • Memory can be deallocated (free/delete) dynamic space whenever we are done with them.
  • Thus, one can always have exactly the amount of space required – no more, no less.
  • Memory size can be reallocated if needed.

Disadvantages:

  • As the memory is allocated during runtime, it requires more time.
  • Memory needs to be freed by the user when done. This is important as it is more likely to turn into bugs that are difficult to find.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads