Dynamic Memory Allocation in C

Learn via video course
FREE
View all courses
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
Topics Covered

In programming, particularly in C, managing memory efficiently is crucial. This begins with understanding the distinction between Static and Dynamic Memory Allocation. Static Memory Allocation, occurring at compile-time, assigns a fixed memory space to variables or arrays. However, this predefined space can sometimes be insufficient.

Dynamic Memory Allocation, on the other hand, addresses this limitation by allowing memory allocation and deallocation during run-time. This is achieved through library functions like malloc(), calloc(), realloc(), and free(). Dynamic Memory Allocation is pivotal in C programming, as it is integral to various data structures such as Linked Lists, Stacks, Queues, and Trees, providing flexibility and efficiency in memory management.

Difference between Static Memory Allocation and Dynamic Memory Allocation

Now, let us see some differences in Static Memory Allocation and Dynamic Memory Allocation.

Static Memory AllocationDynamic Memory Allocation
Constant (Invariable) memory is reserved at compile-time of our program that can't be modified.Dynamic (Variable) memory is reserved at run-time of our program that can be modified.
It is used at compile-time of our program and is also known as compile-time memory allocation.It is used at run-time of our program and is also known as run-time memory allocation.
We can't allocate or deallocate a memory block during run-time.We can allocate and deallocate a memory block during run-time.
Stack space is used in Static Memory Allocation.Heap space is used in Dynamic Memory Allocation.
It doesn't provide reusability of memory, while the program is running. So, it is less efficient.It provides reusability of memory, while the program is running. So, it is more efficient.

How Does Memory Management in C works?

When we execute a C Program, it requires to reserve some memory in the machine to store its variables, functions, instructions and the program file itself. However, we also have a memory segment that we can use dynamically as much memory as the system have and that too during the run-time of a program. So, now let us see the components/segments of memory that are used during the execution of a C program.

There are further four components in which our system's memory is divided:

  1. Stack Segment (Static Memory)
  2. Global Variables Segment (Static Memory)
  3. Instructions / Text Segment (Static Memory)
  4. Heap Segment (Dynamic Memory)

Working of memory management in c

The amount of memory allocated for Stack, Global Variables, and Instructions / Text during compile-time is invariable and cannot be reused until the program execution finishes. However, the Heap segment of the memory can be used at run-time and can be expanded until the system's memory exhausts.

Let's look at the some important points related to all the memory segments :

Instructions / Text

  • Text outside the main() function is stored in the Static Memory.
  • These instructions are stored during compile-time of a program.

Global Variables

  • Global variable also known as static variables and can be declared by two methods,
    • Using static keyword, ex. static int i = 0;
    • Declaring variable outside main() or any other function.
  • These variables are stored in the Static Memory during the compile-time of our program.

Stack

  • Stack is a constant space (memory) allocated by our operating system to store local variables, function calls and local statements that are present in the function definition. It is the major part of the Static Memory in our system.
  • There are some drawbacks of stack space as follows:
    • The memory allocated for stack can't grow during the run-time of an application.
    • We can't allocate or deallocate memory during execution.

Heap

  • Heap is the Dynamic Memory of our program, It can be also be imagined as a big free pool of memory available to us. The space occupied by heap section is not fixed, it can vary during the run-time of our program and there are functions to perform allocation and deallocation of memory blocks during run-time.
  • Heap space can grow as long as we do not run out of the system's memory itself, however it is not in the best interest of a programmer to exhaust the system's memory, so we need to be really careful while using the heap space in our program.

Note : A machine's memory is one of the most useful resource available to us that can be used as both Statically and Dynamically. So, we have to make sure to manage it well and not waste it during the execution of our program.

Memory Allocation Process

Let us now see how our Operating System processes the allocation of memory through an example. We will see how the memory is allocated at compile-time in this section using the example of calculating Greatest Common Divisor (GCD) and Least Common Multiple (LCM).

C Program :

Output :

Explanation of Memory Allocation Process :

Explanation of Memory Allocation Process

  • The first rectangular box represents the memory reserved for text / instructions, second box as memory reserved for global variables section, third box as the space reserved for stack and fourth box represents the heap space.
  • When we run our program, first the main() function is called, then some amount of memory from the stack frame is allocated for the execution of main() function and as sum is a global variable, it has been given a space in the global segment.
  • Heap space remains empty throughout the execution of the program as there is no allocation of memory during run-time.
  • The amount of memory allocated for a function in the stack can be called as a stack frame. All of the local variables, arguments and the information in a function is stored within the stack frame allocated to that function and as soon as a function returns something or reaches its last statement, it is cleared from the stack memory.
  • When the main() finishes, program also finishes. In the end, space occupied by our global variables also gets cleared.

Introduction to Dynamic Memory Allocation in C

Dynamic Memory Allocation in C is a process in which we allocate or deallocate a block of memory during the run-time of a program. There are four functions malloc(), calloc(), realloc() and free() present in <stdlib.h> header file that are used for Dynamic Memory Allocation in our system. It can also be referred to as a procedure to use Heap Memory in which we can vary the size of a variable or Data Structure (such as an Array) during the lifetime of a program using the library functions.
Dynamic Memory Allocation is considered as a very important concept in the field of Data Structures and is used in almost every Data Structures like Linked Lists, Stacks, Dynamic Arrays, Queue, etc.

Now, Let us see the definition, syntax and some examples of each library functions below.

C malloc() Method

malloc() is a method in C which is used to allocate a memory block in the heap section of the memory of some specified size (in bytes) during the run-time of a C program. It is a library function present in the <stdlib.h> header file.

Syntax of malloc()

  • General Syntax:

malloc() function takes size in bytes as an argument and returns a void pointer, so we have to type cast the malloc() function to the required data type. malloc() does not initialises the allocated memory block, so initially it contains a garbage value.

  • Defined in header <stdlib.h> as : void* malloc( size_t size );
    • size : number of bytes to be allocated
  • Example Syntax:

In the above statement, we have assigned and allocated a block of size 4-bytes (64-bit compiler) with cast data type as integer to an integer pointer ptr during the run-time of our program.

We can simply pass number of bytes instead of using sizeof() in argument, both are correct, but sizeof() automatically takes care of the type of compiler and operating system that can cause changes in sizes of different data types on different compilers and operating systems, so it is recommended to use sizeof() function in Dynamic Memory Allocation in C.

Example of malloc()

Let's see an example to allocate a memory block of size 1-byte to a char pointer ptr during run-time using malloc().

C Program :

Output :

Explanation :

  • In the main() function, first we have declared and initialized a char pointer ptr with a dynamic memory block allocated using malloc() function.
  • (char *)malloc(sizeof(char)) returns address of a char block of size 1-byte.
  • char ptr contains the address of the memory block returned by the malloc() function.
  • Now, if the system memory is exhausted it will print Memory Error! (ptr = NULL) in the output console, else we have assigned character S in the memory block pointed by ptr and printf("%c", *ptr); prints S in the output.
  • return 0; exits the program successfully.

C calloc() Method

calloc() is a method in C which is also used to allocate memory blocks in the heap section, but it is generally used to allocate a sequence of memory blocks (contiguous memory) like an array of elements. It is also present in <stdlib.h> header file.

Syntax of calloc()

  • General Syntax:

calloc() function takes two arguments, first is the size of the array (number of elements) and second is the sizeof() data type (in bytes) of which we have to make an array.

  • Defined in header <stdlib.h> as :
  • num : number of elements
  • size : size of each element
  • Example Syntax: int *arr = (int *)calloc(5, sizeof(int));

In the above statement, we are allocating an integer array of size 5 at run-time and assigning it to an integer pointer arr, arr will store the address of the very first element of the allocated array.

Example of calloc()

We will see an example to allocate an character array of size n using calloc() method.

C Program :

Input:

Output:

Scaler Topics

Explanation :

  • In the main() function, first we have declared a integer variable n as it is the size of the array or string that we are going to store in our dynamic memory.
  • We have declared and initialized a char pointer ptr with the dynamic array memory allocated using calloc() function.
  • (char *)calloc(n, sizeof(char)) returns address of first element in the char array.
  • str contains the address of the first element of the array.
  • Now, if the system memory is exhausted it will print Memory Error! (str = NULL) in the output console, else we have assigned a string Scaler Topics in our example output.
  • printf("%c", *str); statement inside the for loop will print each character of the Scaler Topics string in the output.
  • return 0; exits the program successfully.

C free() Method

free() as the name suggests is used to free or deallocate a memory block previously allocated using malloc() and calloc() functions during run-time of our program.

Syntax of free()

  • General syntax:

free() takes one argument and it is the pointer containing the address of the memory block that is to be freed or deallocated.

  • Defined in header <stdlib.h> as :
  • Example :

In the above statement, we are deallocating memory block(s) pointed by a pointer arr in the memory.

Example 1 : malloc() and free()

Let's extend our malloc() example and add free() method in it.

C Program :

Output :

(output garbage values are compiler dependent)

Explanation :

  • We have allocated a char block of size 1-byte using malloc() method and assigned it to a character pointer ptr.
  • We are using the free() method to deallocate the memory block pointed by the pointer ptr in the above example.
  • After deallocation of memory, ptr acts as a Dangling Pointer and is not pointing to any location. It now contains some garbage value.
  • Assign NULL to the pointer ptr after using free() method to avoid garbage values in our program.

Example 2 : calloc() and free()

In this example, let's also use our previous example of calloc() and add free() in it.

C Program :

Input:

Output:

Scaler Topics
garbage value

(output garbage values are compiler dependent)

Explanation :

  • We have allocated an array of size n using calloc() method and assigned it to a character pointer str.
  • We are using the free() method to deallocates the whole array memory pointed by the pointer str in the above example.
  • After deallocation of memory, str acts as a Dangling Pointer and is not pointing to any location. It now contains some garbage value.
  • Assign NULL to the pointer str after using free() method to avoid garbage values in our program.

How to deallocate memory using free()

When we allocate a memory block using malloc() or calloc(), the address of the memory block is stored in a pointer that points to the allocated memory.
We can easily deallocate a memory block allocated by malloc() or calloc() method just by passing the pointer containing the address of the block that is to be deallocated in to the free() method as an argument.

We have seen in the above examples of malloc() and calloc() to use free() function to deallocate memory block(s). Let's see how free() works through a diagram.

This is an example of deallocation of integer memory block using free() function, previously allocated using malloc() function.

deallocate memory using free()

Now, let us see how we can deallocate a memory block without using free() function.

How to deallocate memory without using free()

We can deallocate a memory block without using free() function, alternatively using the realloc() function, which is used in reallocation of memory blocks.

  • realloc(ptr, 0); statement is the same as free(ptr);.

We will see more about this in the realloc() section and an example where we deallocate a memory block using realloc().

C realloc() Method

realloc() is also a method in C that is generally used to reallocate a memory block, here re-allocate means to increase or decrease the size of a memory block previously allocated using malloc() or calloc() methods. It can also be used to completely allocate or deallocate a memory block on its own, we will see how to do it in the examples below.

Syntax of realloc()

  • General syntax : (cast-data-type *)realloc(ptr, new-size-in-bytes)

realloc() takes two arguments, one is the pointer pointing the the memory which is to be realloacted and second is the new size in bytes.

  • Defined in header <stdlib.h> as : void *realloc( void *ptr, size_t new_size );
    • ptr : pointer to the memory area to be reallocated
    • new_size : new size of the array in bytes
  • Example : int *arr2 = (int *)realloc(arr, (n / 2) * sizeof(int));

In the above statement, we are reallocating arr pointer's memory to reduce it to half and assigning it to arr2 pointer, other half of the array will now contain garbage values.

return value of realloc()

realloc() returns the address of the re-allocated memory block.

  • realloc() function need to be type casted because the address returned by the realloc() does not represent any data type.
  • realloc() function may change the address of the previously allocated block, so it is recommended to store the new address in pointer or use some new pointer to store the reallocated address.

Examples of realloc()

Reallocating memory allocated by malloc() and calloc() using realloc()

C Program :

Input

Output :

(output garbage values are compiler dependent)

Explanation :

  • First, We have allocated an integer array memory block of size n using malloc() and calloc() assigned it to integer pointers arr1 and arr2 respectively.
  • If the system's memory is exhausted, we print Memory Error and exit, else we are filling index and reverse index values in arr1 and arr2 respectively.
  • Now, we are using realloc() function to reduce the size of first array arr1 to half and assigning it to arr3 pointer, then increasing the size of second array arr2 to double and assigning it to arr4 pointer.
  • If arr3 or arr4 is NULL then reallocation failed, else we are printing the array values in the output window.
  • arr3 is reduced to half so the other half will contain garbage values, and same in arr4 the size of of array is doubled so the other half will contain garbage values.

Allocation and Deallocation of memory using realloc()

Output:

(output garbage values are compiler dependent)

Explanation :

  • In the main() function, first we have declared a Null Integer pointer.
  • We have allocated an integer block of memory using the realloc() function to the pointer ptr.
  • If ptr contains NULL it shows Memory Error in the output, else we have stored 7 value in the memory block and printed 7 in the output.
  • Now, We have freed the memory block using realloc(ptr, 0) statement. ptr is a Dangling Pointer now, it contains some garbage values.
  • Assign NULL to ptr to avoid garbage values.

malloc() vs calloc()

As we know, malloc() and calloc() both are library functions that are used to allocate memory block(s) during the run-time of a program. But, there are some differences in malloc() and calloc() methods and we are going see them below.

malloc() methodcalloc() method
It is generally used to allocate a single memory block of the given size (in bytes) during the run-time of a program.It is generally used to allocate contiguous (multiple) blocks of memory of given size (in bytes) during the run-time of a program.
It doesn't initializes the allocated memory block and contains some garbage value.It initializes all the allocated memory blocks with 0 (zero) value.
malloc() takes a single arugment i.e. the size of memory block that is to be allocated.calloc() takes two arguments i.e. the number of elements and the size of one element that are to be allocated.
syntax: (cast-data-type *)malloc(size-in-bytes)syntax: (cast-data-type *)calloc(num, size-in-bytes)
Example : float *ptr = (float *)malloc(sizeof(float));Example : float *ptr = (float *)calloc(10, sizeof(float));

Note : malloc(n * sizeof(int)); and calloc(n, sizeof(int)); both allocates the same amount of memory, but malloc() function does't initialize the elements in the memory(garbage values), while the calloc() function initializes all the element in the memory to 0.

Conclusion

  • Learning about Dynamic Memory Allocation in C, and to know how the space is allocated (how memory management works) is always in the best interest of programmers.
  • Allocation and Deallocation of memory blocks during run-time in C are performed using the library functions malloc(), calloc(), free() and realloc(). This process is known as Dynamic Memory Allocation in C.
  • malloc() and calloc() are used to allocate a memory block, while realloc() is used to resize the dynamically allocated memory and free() is used to deallocate a memory block.
  • We have learned all the types of memory allocation and deallocation processes by seeing the examples of all library functions.
  • We have seen the differences between malloc() and calloc() functions.

See Also: