Back to C Programming
2026-01-317 min read

15.3 Dynamic Memory Allocation

Learn 15.3 Dynamic Memory Allocation step by step with clear examples and exercises.

Here's a revised C programming lesson on "15.3 Dynamic Memory Allocation" that addresses the issues mentioned:


Why This Matters

Why This Matters

Dynamic memory allocation is an essential skill for any C programmer, as it allows you to create variables at runtime and adapt to varying data sizes during execution. This flexibility can lead to more efficient programs, better memory management, and the ability to handle complex data structures like linked lists and trees.

Real-world applications

Dynamic memory allocation is crucial in many real-world scenarios, such as:

  1. Handling large datasets from files or databases
  2. Processing user input dynamically
  3. Creating dynamic data structures like linked lists and trees
  4. Implementing memory pools for optimizing memory usage
  5. Allocating memory for custom data structures like structs and unions
  6. Developing libraries that require dynamic memory management
  7. Building efficient algorithms that need to adapt to varying input sizes

Prerequisites

Before diving into dynamic memory allocation, it's essential to have a solid understanding of the following topics:

  1. Basic C syntax (variables, operators, control structures)
  2. Arrays in C
  3. Pointers in C
  4. Structures and data types in C
  5. File I/O in C
  6. Understanding of pointer arithmetic and dereferencing
  7. Knowledge of conditional statements and loops
  8. Basic memory concepts (heap, stack, and memory allocation)
  9. Familiarity with linked lists and other dynamic data structures
  10. Experience debugging common memory-related issues in C programs

Core Concept

Dynamic memory allocation in C is primarily achieved using the malloc() function from the standard library, but there are also other functions like calloc(), realloc(), and free(). These functions allow you to allocate, initialize, resize, and deallocate memory blocks as needed.

malloc()

The malloc() function allocates a block of memory with a specified size and returns a pointer to that memory. Let's explore how to use malloc() with an example:

#include <stdio.h>
#include <stdlib.h>

int main() {
int *arr; // Declare a pointer to an integer
int size = 10; // Define the array size

arr = (int *) malloc(size * sizeof(int)); // Allocate memory for the array

if (arr == NULL) { // Check if the allocation was successful
printf("Memory allocation failed.\n");
return 1;
}

// Use the allocated memory as needed...

free(arr); // Don't forget to free the memory when done!
return 0;
}

In this example, we first declare a pointer arr to an integer. We then define the size of the array and use malloc() to allocate memory for it. The sizeof(int) is used to determine the size of each element in bytes. If the allocation is successful, we can use the memory as needed, and when done, we must free the memory using the free() function to avoid memory leaks.

calloc()

The calloc() function is similar to malloc(), but it initializes the allocated memory with zeros:

int *arr = calloc(10, sizeof(int)); // Allocate and initialize an array of 10 integers

realloc()

The realloc() function resizes an existing memory block. It can be used to dynamically grow or shrink an allocated memory block:

arr = realloc(arr, size * sizeof(int)); // Resize the array if needed

free()

The free() function is used to deallocate previously allocated memory blocks. It's essential to call free() when you're done using the memory to avoid memory leaks:

free(arr); // Free the allocated memory

Worked Example

Let's create a simple program that dynamically allocates an array of 20 integers, initializes them with user input, finds the maximum number, and frees the memory:

#include <stdio.h>
#include <stdlib.h>

int max_element(int *arr, int size) {
int i, max = arr[0];
for (i = 1; i < size; ++i) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}

int main() {
int *arr; // Declare a pointer to an integer
int size, i; // Define variables for array size and loop counter

printf("Enter the number of elements: ");
scanf("%d", &size);

arr = (int *) malloc(size * sizeof(int)); // Allocate memory for the array

if (arr == NULL) { // Check if the allocation was successful
printf("Memory allocation failed.\n");
return 1;
}

printf("Enter %d integers:\n", size);
for (i = 0; i < size; ++i) {
scanf("%d", &arr[i]); // Read user input and store in the array
}

int max = max_element(arr, size); // Find the maximum number
printf("\nThe maximum integer is: %d\n", max);

free(arr); // Free the allocated memory
return 0;
}

In this example, we first declare a pointer arr to an integer. We then define the size of the array and use malloc() to allocate memory for it. After that, we read user input and store it in the array. When done, we find the maximum number using the max_element() function and free the memory using free().

Common Mistakes

  1. **Forgetting to include `**: The malloc(), calloc(), realloc(), and free()` functions are declared in this header file, so don't forget to include it!
  2. Not checking for NULL pointer: Always check if the memory allocation was successful by comparing the returned pointer with NULL. If the pointer is NULL, handle the error appropriately.
  3. Leaking memory: Make sure to free the allocated memory when you're done using it to avoid memory leaks.
  4. Accessing unallocated memory: Be careful not to access memory that hasn't been allocated yet or has already been freed, as this can lead to undefined behavior and program crashes.
  5. Incorrect memory deallocation: When freeing memory, ensure you pass the correct pointer (the one returned by malloc() or a derived pointer) and not some other pointer.
  6. Memory fragmentation: Over time, dynamic memory allocation can lead to memory fragmentation, where small unused blocks of memory are scattered throughout the heap. This can be mitigated using techniques like compaction or using specialized libraries for memory management.
  7. Buffer overflow: Dynamic memory allocation can potentially lead to buffer overflows if you don't carefully validate user input and ensure it fits within the allocated memory.
  8. Memory corruption: Improper use of dynamic memory allocation can lead to memory corruption, which can cause unpredictable behavior and crashes. Always be mindful of your memory usage and follow good programming practices.
  9. Not handling errors gracefully: When dealing with dynamic memory allocation, it's essential to handle errors appropriately, such as by providing user-friendly error messages or exiting the program gracefully when necessary.
  10. Using incorrect function for the task: Choose the appropriate function (malloc(), calloc(), or realloc()) based on your needs and ensure you use it correctly.

Practice Questions

Question 1: Dynamic Memory Allocation

Write a C program that dynamically allocates an array of 20 integers, initializes them with user input, finds the sum of even numbers, and frees the memory.

Question 2: Linked List Implementation

Implement a simple linked list in C using dynamic memory allocation for nodes. The linked list should support insertion at the beginning and deletion from the end. Write functions to create an empty list, insert an element at the beginning, delete an element from the end, and free the memory of the linked list when done.

Question 3: Memory Allocation Optimization

Write a C program that reads a file containing integers and dynamically allocates memory for them using malloc(). However, instead of reading all the numbers into memory at once, read them in chunks of 100 numbers each to optimize memory usage. Implement functions to read the next chunk when needed and free the memory when done.

FAQ

How do I find the memory usage of a program in C?

You can use the mallinfo() function to get detailed information about memory allocation, including the total allocated and free memory. The mallinfo() function returns a mallinfo structure containing various fields related to memory allocation.

What happens if I don't free memory in C?

If you don't free memory that was dynamically allocated using malloc(), calloc(), or realloc(), the memory will not be reclaimed, leading to a memory leak. Over time, this can cause your program to consume excessive resources and potentially crash due to insufficient memory.

How do I find the size of an allocated memory block in C?

You can use the sizeof operator to determine the size of each element in the allocated memory block. For example, if you have an array of integers, you can use sizeof(int) to get the size of each integer in bytes:

int *arr = malloc(10 * sizeof(int)); // Allocate an array of 10 integers

Can I allocate memory for a struct in C?

Yes, you can allocate memory for a struct using malloc(). First, define the struct and its members, then use malloc() to allocate memory for the entire struct:

struct MyStruct {
int id;
char name[50];
};

struct MyStruct *my_struct = malloc(sizeof(struct MyStruct)); // Allocate memory for a single struct

How can I dynamically allocate a two-dimensional array in C?

To dynamically allocate a two-dimensional array, you can use a loop to allocate each row and store the pointers in an array of pointers:

int rows = 10;
int cols = 20;
int **arr = malloc(rows * sizeof(int*)); // Allocate memory for the rows
for (int i = 0; i < rows; ++i) {
arr[i] = calloc(cols, sizeof(int)); // Allocate memory for each column in the current row
}