DevAcademia
C++C#CPythonJava
  • C Basics

  • Introduction to C
  • Getting Started with C
  • C Syntax
  • C Output
  • C Comments
  • C Variables
  • C Data Types
  • C Constants
  • C Operators
  • C Booleans
  • C If...Else Statements
  • C Switch Statement
  • C While Loops
  • C For Loops
  • C Break and Continue
  • C Strings
  • C User Input
  • C Memory Address
  • C Pointers
  • C Files
  • C Functions

  • C Functions
  • C Function Parameters
  • C Scope
  • C Function Declaration
  • C Recursion
  • C Math Functions
  • C Structures

  • C Structures
  • C Structs & Pointers
  • C Unions
  • C Enums

  • C Enums
  • C Memory

  • C Allocate Memory
  • C Access Memory
  • C Reallocate Memory
  • C Deallocate Memory
  • C Structs and Memory
  • C Memory Example
  • C Quiz

  • C Quiz
  • C Basics

  • Introduction to C
  • Getting Started with C
  • C Syntax
  • C Output
  • C Comments
  • C Variables
  • C Data Types
  • C Constants
  • C Operators
  • C Booleans
  • C If...Else Statements
  • C Switch Statement
  • C While Loops
  • C For Loops
  • C Break and Continue
  • C Strings
  • C User Input
  • C Memory Address
  • C Pointers
  • C Files
  • C Functions

  • C Functions
  • C Function Parameters
  • C Scope
  • C Function Declaration
  • C Recursion
  • C Math Functions
  • C Structures

  • C Structures
  • C Structs & Pointers
  • C Unions
  • C Enums

  • C Enums
  • C Memory

  • C Allocate Memory
  • C Access Memory
  • C Reallocate Memory
  • C Deallocate Memory
  • C Structs and Memory
  • C Memory Example
  • C Quiz

  • C Quiz

Loading C tutorial…

Loading content
C MemoryTopic 61 of 64
←PreviousPrevNextNext→

C Deallocate Memory

Introduction to Memory Deallocation

Memory deallocation is the process of returning dynamically allocated memory back to the system. Proper memory management is crucial for preventing memory leaks and ensuring efficient resource usage in C programs.

Key aspects of memory deallocation:

- Releasing memory when it's no longer needed

- Preventing memory leaks and resource exhaustion

- Maintaining program stability and performance

- Following proper cleanup procedures for complex data structures

The free() Function

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

int main(void) {
    int *numbers;
    int count = 5;

    numbers = (int*)malloc(count * sizeof(int));
    if (numbers == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }

    for (int i = 0; i < count; i++) {
        numbers[i] = (i + 1) * 10;
    }

    printf("Array values: ");
    for (int i = 0; i < count; i++) {
        printf("%d ", numbers[i]);
    }

    free(numbers);
    numbers = NULL; // avoid dangling pointer

    printf("\nMemory successfully freed.\n");
    return 0;
}
Output
Array values: 10 20 30 40 50
Memory successfully freed.
ℹ️ Note: Always check if memory allocation was successful before using the pointer. Set pointers to NULL after freeing to avoid dangling pointers. Calling free(NULL) is safe and has no effect.

Common free() Mistakes and Pitfalls

⚠️ Warning: Double freeing, freeing non-heap memory, and accessing freed memory are common sources of bugs and crashes in C programs.
Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    int *ptr = (int*)malloc(sizeof(int));
    if (!ptr) return 1;
    *ptr = 42;
    free(ptr);
    // free(ptr); // Double free - undefined behavior

    int x = 10;
    // free(&x); // Freeing stack memory - undefined behavior

    char *str = (char*)malloc(10 * sizeof(char));
    if (!str) return 1;
    strcpy(str, "Hello");
    free(str);
    // printf("%s\n", str); // Accessing freed memory - undefined behavior

    for (int i = 0; i < 100; i++) {
        int *leak = (int*)malloc(sizeof(int));
        if (!leak) break;
        *leak = i;
        // Forgot to free(leak) - memory leak (intentional example)
    }

    int *proper = NULL;
    for (int i = 0; i < 100; i++) {
        proper = (int*)malloc(sizeof(int));
        if (proper != NULL) {
            *proper = i;
            free(proper);
            proper = NULL;
        }
    }

    printf("Demonstrated common free() mistakes (commented out)\n");
    return 0;
}

Memory Leak Detection and Prevention

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

int main(void) {
    int *leaky = (int*)malloc(100 * sizeof(int));
    // Intentionally not freeing 'leaky' to demonstrate a leak

    int *clean = (int*)malloc(50 * sizeof(int));
    if (clean != NULL) {
        for (int i = 0; i < 50; i++) {
            clean[i] = i;
        }
        free(clean);
        clean = NULL;
    }

    printf("Program completed. Memory leak present.\n");
    return 0;
}
ℹ️ Note: In real projects, use tools like Valgrind, AddressSanitizer, or specialized memory debugging libraries to detect memory leaks.

Structured Deallocation for Complex Data

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

typedef struct {
    char *name;
    int age;
    float *scores;
    int scoreCount;
} Student;

Student* createStudent(const char *name, int age) {
    if (name == NULL) return NULL;
    Student *student = (Student*)malloc(sizeof(Student));
    if (student == NULL) return NULL;

    student->name = (char*)malloc(strlen(name) + 1);
    if (student->name == NULL) {
        free(student);
        return NULL;
    }
    strcpy(student->name, name);

    student->age = age;
    student->scores = NULL;
    student->scoreCount = 0;
    return student;
}

void addScore(Student *student, float score) {
    if (student == NULL) return;
    float *newScores = (float*)realloc(student->scores,
                                      (student->scoreCount + 1) * sizeof(float));
    if (newScores == NULL) return; // keep old pointer if realloc fails
    student->scores = newScores;
    student->scores[student->scoreCount] = score;
    student->scoreCount++;
}

void freeStudent(Student *student) {
    if (student == NULL) return;
    free(student->name);
    free(student->scores);
    free(student);
}

int main(void) {
    Student *john = createStudent("John Doe", 20);
    if (john != NULL) {
        addScore(john, 85.5f);
        addScore(john, 92.0f);
        addScore(john, 78.5f);

        printf("Student: %s, Age: %d\n", john->name, john->age);
        printf("Scores: ");
        for (int i = 0; i < john->scoreCount; i++) {
            printf("%.1f ", john->scores[i]);
        }
        printf("\n");
        freeStudent(john);
        john = NULL;
    }
    printf("Student memory properly deallocated.\n");
    return 0;
}
Output
Student: John Doe, Age: 20
Scores: 85.5 92.0 78.5
Student memory properly deallocated.
ℹ️ Note: For complex data structures, create dedicated cleanup functions that handle all nested allocations in reverse order of creation.

Best Practices for Memory Deallocation

  • Always free memory when it's no longer needed
  • Set pointers to NULL after freeing to avoid dangling pointers
  • Free memory in the reverse order of allocation
  • Use consistent patterns for allocation/deallocation
  • Consider using tools like Valgrind to detect memory leaks
  • For complex data structures, create dedicated cleanup functions
  • Be especially careful with error paths - ensure all allocations are freed
  • Document ownership and responsibility for freeing memory
  • free(NULL) is safe and does nothing
  • When using realloc, assign to a temporary pointer first to avoid losing the original allocation on failure
  • In C, prefer not casting malloc/calloc/realloc results; include so the compiler knows the prototypes
Test your knowledge: C Deallocate Memory
Quiz Configuration
4 of 8 questions
Sequential
Previous allowed
Review enabled
Early close allowed
Estimated time: 5 min
C MemoryTopic 61 of 64
←PreviousPrevNextNext→