Back to C Programming
2026-07-155 min read

C free()

Learn C free() step by step with clear examples and exercises.

Why This Matters

In C programming, dynamic memory allocation is essential for creating arrays or structures of varying sizes during runtime. Managing this dynamically allocated memory efficiently is crucial to avoid memory leaks and ensure the smooth execution of programs. The free() function plays a vital role in this process by deallocating the allocated memory when it's no longer needed.

Prerequisites

Before diving into the core concept of free(), you should be familiar with:

  • Basic C programming concepts such as variables, data types, and operators
  • Understanding of pointers in C
  • Dynamic memory allocation using malloc() and calloc() functions
  • Knowledge of conditional statements (if-else) for checking memory allocation status

Core Concept

Allocating Memory with malloc()

Before we delve into free(), let's quickly review how to allocate memory dynamically using the malloc() function:

int *ptr;
ptr = (int *)malloc(10 * sizeof(int));

In this example, we create a pointer ptr of type int*. We then use malloc() to allocate memory for an array of 10 integers. The sizeof(int) ensures that the correct amount of memory is allocated.

Using free() to Deallocate Memory

Now, let's see how we can use the free() function to deallocate this memory:

if (ptr != NULL) {
free(ptr);
}

The free() function takes a pointer as an argument and releases the memory block that was previously allocated by malloc(). Note that that freeing memory before using it again is crucial for efficient program execution. We also added a conditional check to ensure we only call free() if the pointer is not null, which helps prevent potential errors.

When to Use free()

  • After processing dynamically allocated data, you should always call free() on the pointer used for allocation.
  • If you have multiple pointers pointing to the same memory block, free each one separately.
  • Avoid calling free() on a null pointer or a pointer that was not previously allocated with malloc(), calloc(), or realloc().

Worked Example

Let's create a simple program that dynamically allocates an array of integers, processes the data, and then frees the memory:

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

int main() {
int *arr;
int size = 10;
int i;

// Allocate memory for an array of integers
arr = (int *)malloc(size * sizeof(int));

if (arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}

// Initialize the array with some values
for (i = 0; i < size; i++) {
arr[i] = i * 2;
}

// Process the data
printf("Original array:\n");
for (i = 0; i < size; i++) {
printf("%d ", arr[i]);
}

// Free the allocated memory
free(arr);

return 0;
}

In this example, we allocate an array of 10 integers using malloc(), initialize the values, process the data, and then release the memory with free().

Worked Example

Now let's modify our previous example to dynamically increase the size of the array during runtime:

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

int main() {
int *arr;
int size = 10;
int i, newSize;

// Allocate memory for an array of integers
arr = (int *)malloc(size * sizeof(int));

if (arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}

// Initialize the array with some values
for (i = 0; i < size; i++) {
arr[i] = i * 2;
}

// Process the data
printf("Original array:\n");
for (i = 0; i < size; i++) {
printf("%d ", arr[i]);
}

// Check if we need more memory
newSize = size * 2;
if (newSize > size) {
// Reallocate the memory and copy the old data
arr = realloc(arr, newSize * sizeof(int));

if (arr == NULL) {
printf("Memory reallocation failed!\n");
return 1;
}

for (i = size; i < newSize; i++) {
arr[i] = -1; // Fill the new memory with a sentinel value
}
}

// Process the expanded data
printf("\nExpanded array:\n");
for (i = 0; i < newSize; i++) {
printf("%d ", arr[i]);
}

// Free the allocated memory
free(arr);

return 0;
}

In this example, we first allocate an array of 10 integers. Then, we process the data and check if we need more memory. If so, we reallocate the memory using realloc(), copy the old data to the new memory, and fill the new memory with a sentinel value. After processing the expanded data, we free the allocated memory.

Common Mistakes

1. Not checking for malloc() failure

Always check if malloc() successfully allocates memory before proceeding with further operations:

if (ptr == NULL) {
printf("Memory allocation failed!\n");
return 1; // or handle the error appropriately
}

2. Freeing memory multiple times

Avoid freeing the same memory block more than once, as this can lead to undefined behavior:

int *ptr = (int *)malloc(10 * sizeof(int));
// ...
free(ptr);
// This is incorrect! Don't do it again.
free(ptr);

3. Freeing unallocated memory

Never call free() on a null pointer or a pointer that was not previously allocated:

int *ptr = NULL; // This is a null pointer
free(ptr); // Do not do this! It will cause undefined behavior.

4. Not checking for realloc() failure

Always check if realloc() successfully reallocates memory before proceeding with further operations:

if (newPtr == NULL) {
printf("Memory reallocation failed!\n");
return 1; // or handle the error appropriately
}

Practice Questions

  1. Write a program to dynamically allocate an array of 20 characters and input strings from the user. Process the strings and then free the memory.
  2. Create a program that dynamically allocates a 2D array (matrix) of integers, initializes it with some values, processes the data, and then frees the memory.
  3. Write a function that takes an array of integers as a parameter, sorts the array using a sorting algorithm like quicksort or mergesort, and then frees the memory allocated to the array.
  4. Modify the previous example to handle the case when there's not enough memory for reallocation, by dynamically increasing the size in smaller increments until sufficient memory is available.

FAQ

Q1: Can I use free() on pointers returned by calloc() or realloc()?

A1: Yes, you can use free() on pointers returned by both calloc() and realloc(). The function works the same way for all three functions.

Q2: What happens if I don't free dynamically allocated memory in C?

A2: If you don't free dynamically allocated memory, it will lead to a memory leak. Over time, your program will consume more and more memory, eventually causing it to crash or perform poorly.

Q3: Can I use free() on a pointer that was previously freed?

A3: No, you cannot call free() on a pointer that was already freed. Doing so may cause undefined behavior in your program.

Q4: What is the difference between malloc(), calloc(), and realloc() functions?

A4: The main difference lies in how they initialize the allocated memory:

  • malloc() allocates uninitialized memory of the specified size.
  • calloc() allocates zero-initialized memory of the specified size.
  • realloc() changes the size of a previously allocated memory block and may move its contents to a new location. If the new size is larger, the remaining bytes are set to zero.