Dynamic memory allocation allows a C program to request memory while the program is running. It is useful when the amount of memory needed is not known at compile time.
<stdlib.h> header file. Memory obtained dynamically
should be released with free() when it is no longer needed.
Dynamic memory allocation means allocating memory during program execution instead of deciding the required amount completely at compile time.
For example, if a program needs an array whose size is entered by the user, dynamic memory allocation can be used.
Dynamic memory is useful when the required memory size can change at runtime.
The main dynamic memory allocation functions are declared in
<stdlib.h>.
#include <stdlib.h>
Functions such as malloc(), calloc(),
realloc(), and free() are provided through this
header.
The malloc() function allocates a block of uninitialized
memory.
int *ptr;
ptr = malloc(5 * sizeof(int));
The requested memory is allocated from the dynamic memory area and its address is returned.
The general form is:
pointer = malloc(number_of_bytes);
For example:
int *numbers = malloc(10 * sizeof *numbers);
Using sizeof *numbers helps keep the allocation tied to the
pointer's actual pointed-to type.
If allocation succeeds, malloc() returns a pointer to the
allocated memory.
int *ptr = malloc(sizeof *ptr);
The pointer can then be used to access the allocated object.
Memory allocation can fail. Therefore, the returned pointer should be checked before using it.
int *ptr = malloc(sizeof *ptr);
if(ptr == NULL)
{
printf("Memory allocation failed");
}
else
{
*ptr = 100;
}
Memory returned by malloc() is not initialized to zero.
Its initial contents are indeterminate.
int *ptr = malloc(5 * sizeof *ptr);
Initialize the allocated memory before reading its values.
The calloc() function allocates memory for multiple elements
and initializes all allocated bytes to zero.
int *numbers = calloc(5, sizeof *numbers);
This allocates space for five integers.
The general syntax is:
pointer = calloc(number_of_elements, size_of_each_element);
Example:
int *numbers = calloc(10, sizeof *numbers);
| malloc() | calloc() |
|---|---|
| Takes one size argument | Takes number of elements and element size |
| Memory is not initialized | Allocated bytes are initialized to zero |
| Useful for a single block of requested bytes | Useful for allocating multiple elements |
The free() function releases dynamically allocated memory.
int *ptr = malloc(sizeof *ptr);
if(ptr != NULL)
{
*ptr = 100;
free(ptr);
ptr = NULL;
}
After freeing memory, setting the pointer to NULL can help
avoid accidentally using the old address.
Dynamically allocated memory remains allocated until it is released or the program terminates.
Failing to release memory that is no longer needed can cause a memory leak.
The realloc() function changes the size of a previously
allocated memory block.
int *numbers = malloc(5 * sizeof *numbers);
int *temp = realloc(numbers, 10 * sizeof *numbers);
If the reallocation succeeds, the returned pointer represents the resized block.
The general syntax is:
new_pointer = realloc(old_pointer, new_size);
The memory block may be moved to a different location when its size is changed.
It is safer to store the result of realloc() in a temporary
pointer before replacing the original pointer.
int *temp = realloc(numbers, 10 * sizeof *numbers);
if(temp != NULL)
{
numbers = temp;
}
else
{
printf("Reallocation failed");
}
This preserves the original pointer if the reallocation fails.
Dynamic memory allocation can be used to create an array whose size is known only during program execution.
int n;
printf("Enter size: ");
scanf("%d", &n);
int *numbers = malloc(n * sizeof *numbers);
The array can then be accessed using normal indexing.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
printf("Enter number of elements: ");
scanf("%d", &n);
int *numbers = malloc(n * sizeof *numbers);
if(numbers == NULL)
{
printf("Memory allocation failed");
return 1;
}
for(int i = 0; i < n; i++)
{
numbers[i] = i + 1;
}
for(int i = 0; i < n; i++)
{
printf("%d ", numbers[i]);
}
free(numbers);
return 0;
}
Dynamic memory can also be allocated for a structure.
struct Student
{
int id;
float marks;
};
struct Student *student =
malloc(sizeof *student);
The structure can be accessed using the arrow operator.
student->id = 101;
student->marks = 85.5f;
Dynamic memory can be used when the required string storage is determined at runtime.
char *name = malloc(50 * sizeof *name);
if(name != NULL)
{
scanf("%49s", name);
printf("Name = %s", name);
free(name);
}
Always ensure that the input fits inside the allocated memory.
A dynamically allocated array can be accessed using either array indexing or pointer arithmetic.
int *numbers = malloc(5 * sizeof *numbers);
numbers[0] = 10;
numbers[1] = 20;
printf("%d", *(numbers + 1));
free(numbers);
The expression *(numbers + 1) accesses the second element.
struct Student
{
int id;
float marks;
};
int n = 5;
struct Student *students =
malloc(n * sizeof *students);
if(students != NULL)
{
students[0].id = 101;
students[0].marks = 90.0f;
}
This allocates space for multiple structure objects.
A memory leak occurs when dynamically allocated memory is no longer reachable by the program but has not been released.
int *ptr = malloc(100 * sizeof *ptr);
/* ptr is lost without free() */
Repeated memory leaks can cause a program to consume more and more memory.
A dangling pointer is a pointer that refers to memory that has already been released.
int *ptr = malloc(sizeof *ptr);
free(ptr);
/* ptr should not be dereferenced here */
A useful practice is:
free(ptr);
ptr = NULL;
Calling free() more than once on the same allocated pointer
without giving it a new valid allocation can result in undefined behavior.
int *ptr = malloc(sizeof *ptr);
free(ptr);
ptr = NULL;
/* Do not free the old allocation again. */
Setting a pointer to NULL after freeing can help make repeated
cleanup safer because free(NULL) has no effect.
Dynamic memory does not automatically prevent writing outside the allocated block.
int *numbers = malloc(5 * sizeof *numbers);
numbers[0] = 10;
numbers[4] = 50;
/* numbers[5] is outside the allocated array */
Always keep indexes within the allocated range.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
int sum = 0;
printf("Enter number of elements: ");
scanf("%d", &n);
if(n <= 0)
{
printf("Invalid size");
return 1;
}
int *numbers = malloc(n * sizeof *numbers);
if(numbers == NULL)
{
printf("Memory allocation failed");
return 1;
}
for(int i = 0; i < n; i++)
{
printf("Enter number %d: ", i + 1);
scanf("%d", &numbers[i]);
sum += numbers[i];
}
printf("Sum = %d\n", sum);
free(numbers);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *numbers = calloc(3, sizeof *numbers);
if(numbers == NULL)
{
printf("Allocation failed");
return 1;
}
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
int *temp = realloc(numbers, 5 * sizeof *numbers);
if(temp == NULL)
{
free(numbers);
return 1;
}
numbers = temp;
numbers[3] = 40;
numbers[4] = 50;
for(int i = 0; i < 5; i++)
{
printf("%d ", numbers[i]);
}
free(numbers);
return 0;
}
<stdlib.h>.NULL.sizeof when calculating allocation sizes.free() when it is no longer needed.NULL when appropriate.realloc().Create a C program that:
malloc() to allocate an array of student marks.realloc() to increase the array size.free().
This exercise will help you practice malloc(),
realloc(), pointers, arrays, and free().
malloc() allocates uninitialized memory.calloc() allocates memory and initializes the allocated bytes to zero.realloc() changes the size of an existing allocation.free() releases dynamically allocated memory.<stdlib.h>.NULL.sizeof to calculate allocation sizes safely.realloc() should be handled carefully so the original allocation is not accidentally lost on failure.Question: Which function is used to release dynamically allocated memory?