Back to C Programming
2025-12-166 min read

allocation functions

Learn allocation functions step by step with clear examples and exercises.

Why This Matters

Memory management is a crucial aspect of C programming, as it allows for dynamic memory allocation during runtime. Understanding allocation functions is essential to writing efficient, flexible, and robust code that can handle varying input sizes without crashing or using excessive resources.

Prerequisites

Before diving into the core concept of allocation functions, it's important to have a solid understanding of:

  • Basic C syntax and control structures (e.g., loops, conditionals)
  • Variables and data types
  • Pointers and pointer arithmetic
  • Syntax and operators
  • Data Structures and Control Flow (arrays, pointers, structures, loops, conditionals)

Syntax and Operators

  • Arithmetic operators (+, -, *, /, %)
  • Relational operators (<, >, <=, >=, ==, !=)
  • Logical operators (&&, ||, !)
  • Assignment operator (=)
  • Conditional operator (?:)

Data Structures and Control Flow

  • Arrays
  • Pointers
  • Structures
  • Loops (for, while, do-while)
  • Conditionals (if, if-else, switch)

Core Concept

Allocating Memory: malloc(), calloc(), realloc(), free(), free_sized(), free_aligned_sized(), and aligned_alloc()

The primary allocation functions in C are malloc(), calloc(), realloc(), free(), free_sized(), free_aligned_sized(), and aligned_alloc(). These functions dynamically allocate memory for your program to use.

  1. malloc(size): This function allocates an uninitialized block of memory with the size specified by size. The returned pointer points to the first byte of the allocated memory. If the allocation fails, it returns a null pointer.
int *ptr = (int *) malloc(10 * sizeof(int));
  1. calloc(nmemb, size): This function allocates an array of nmemb elements, each of size size, and initializes all the allocated memory to zero. It returns a pointer to the first byte of the allocated memory or a null pointer on failure.
int *ptr = calloc(10, sizeof(int));
  1. realloc(ptr, size): This function reallocates the previously allocated memory block pointed to by ptr and changes its size to size. If the new size is larger than the original size, the remaining bytes after the end of the original block are set to zero. If the new size is smaller, the contents of the original block up to the minimum between the old and new sizes are preserved. If the allocation fails, it returns a null pointer.
int *ptr = (int *) malloc(10 * sizeof(int));
// ... do something with ptr ...
ptr = realloc(ptr, 20 * sizeof(int));
  1. free(ptr): This function frees the memory block pointed to by ptr, making it available for future allocations.
free(ptr);
  1. free_sized(ptr, size): This function deallocates the previously allocated sized memory block pointed to by ptr. It is similar to free(), but it explicitly provides the size of the memory block for better error detection and debugging.
free_sized(ptr, 10 * sizeof(int));
  1. free_aligned_sized(ptr, alignment, size): This function deallocates a previously allocated sized and aligned memory block pointed to by ptr. It is useful when working with hardware that requires specific memory alignments.
free_aligned_sized(ptr, 64, 10 * sizeof(int));
  1. aligned_alloc(alignment, size): This function allocates aligned memory with the specified alignment and size. It is useful when working with hardware that requires specific memory alignments.
void *ptr = aligned_alloc(64, 10 * sizeof(int));

Worked Example

Let's create a simple program that dynamically allocates an array of integers, fills it with user-provided values, and then deallocates the memory.

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

int main() {
int *arr;
int n, i;

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

arr = (int *) malloc(n * sizeof(int));

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

printf("Enter the elements:\n");
for (i = 0; i < n; ++i) {
scanf("%d", &arr[i]);
}

// Process the array...

free(arr);
return 0;
}

Common Mistakes

  1. Forgetting to include stdlib.h: This header file contains declarations for the allocation functions.
  2. Not checking if malloc() or calloc() returned a null pointer: If memory allocation fails, these functions return a null pointer, which should be handled appropriately in your code.
  3. Leaking memory: Failing to deallocate dynamically allocated memory using free().
  4. Using free() on a non-malloc'd pointer: Only use free() on pointers obtained from malloc(), calloc(), or realloc().
  5. Not handling alignment with aligned_alloc(): Make sure the alignment provided is compatible with your hardware requirements.
  6. Not checking for errors when using free_sized() and free_aligned_sized(): Ensure that the pointer and sizes are valid before calling these functions.
  7. Not properly initializing memory allocated by calloc(): Although calloc() initializes the memory to zero, it's essential to ensure that the pointers are pointing to valid memory before using them.
  8. Not checking for array out-of-bounds errors: Always validate user input and index calculations to avoid accessing memory outside the allocated array bounds.
  9. Using incorrect pointer arithmetic: Be mindful of the size of the data type when performing pointer arithmetic.

Practice Questions

  1. Write a program that dynamically allocates an array of doubles, fills it with user-provided values, and then deallocates the memory using free().
  2. Modify the previous example to use calloc() instead of malloc(). How does this affect the initialization of the allocated memory?
  3. Write a program that demonstrates the usage of realloc(). Show how it can be used to resize an array and move its contents.
  4. Write a program that uses free_sized() and free_aligned_sized(). How does this function differ from using regular free()?
  5. Write a program that demonstrates the usage of aligned_alloc(). How does this help with memory alignment, and why is it important for certain hardware configurations?
  6. Write a program that dynamically allocates an array of strings, reads them line by line from a file, and then deallocates the memory using free().
  7. Write a program that dynamically allocates a 2D array (array of arrays) and fills it with user-provided values. Use realloc() to increase the number of rows when necessary.
  8. Write a program that uses aligned_alloc() to allocate memory for a large data structure that requires specific alignment, such as a struct containing large arrays or matrices.
  9. Write a program that demonstrates the usage of free_sized() and free_aligned_sized() in combination with dynamic memory allocation functions to manage memory more efficiently and reduce potential errors.
  10. Write a program that uses malloc(), calloc(), realloc(), and free() to implement a simple dynamic array data structure, where the size of the array can be increased or decreased as needed.

FAQ

  1. Why should I use dynamic memory allocation instead of statically declaring arrays?

Dynamic memory allocation allows you to create data structures with variable sizes at runtime, making your code more flexible and efficient in handling different input sizes.

  1. What happens if I free() a pointer that was not obtained from malloc(), calloc(), or realloc()?

If you free() a pointer that was not obtained from these functions, undefined behavior occurs, which can lead to crashes or memory leaks.

  1. Why is it important to check if malloc() or calloc() returned a null pointer?

Checking for a null pointer ensures that your program handles cases where memory allocation fails gracefully, preventing crashes and making the code more robust.

  1. What is the purpose of aligned_alloc() in C23?

Aligned_alloc() is used to allocate memory with specific alignment requirements, which can help improve performance when working with certain hardware configurations.

  1. Why should I use free_sized() and free_aligned_sized() instead of regular free()?

Using free_sized() and free_aligned_sized() provides more information about the memory being freed, which can help with debugging and error handling.

  1. What are some common mistakes to avoid when using allocation functions in C?

Some common mistakes include forgetting to include stdlib.h, not checking if malloc() or calloc() returned a null pointer, leaking memory by failing to deallocate dynamically allocated memory, using free() on a non-malloc'd pointer, not handling alignment with aligned_alloc(), not checking for errors when using free_sized() and free_aligned_sized(), not properly initializing memory allocated by calloc(), not checking for array out-of-bounds errors, using incorrect pointer arithmetic, and forgetting to deallocate memory allocated from files.

  1. What are some best practices for managing memory in C?

Some best practices include checking for null pointers when using malloc() or calloc(), validating user input and index calculations to avoid accessing memory outside the allocated array bounds, using realloc() to resize arrays as needed, using free_sized() and free_aligned_sized() to manage memory more efficiently and reduce potential errors, and implementing dynamic array data structures to handle variable-sized arrays.