C - Memory Handling

C provides functions for dynamic memory allocation and deallocation, allowing you to manage memory manually for flexible data structures.

Key Functions

  • malloc() - Allocates memory
  • calloc() - Allocates and initializes memory
  • realloc() - Resizes allocated memory
  • free() - Deallocates memory

Examples

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

int main(void) {
    size_t n = 5;
    int *a = malloc(n * sizeof *a);          // allocate
    if (!a) { perror("malloc"); return 1; }
    for (size_t i = 0; i < n; i++) a[i] = (int)(i*i);

    int *b = calloc(n, sizeof *b);           // zero-initialized
    if (!b) { free(a); perror("calloc"); return 1; }

    size_t m = 10;
    int *c = realloc(a, m * sizeof *a);      // resize
    if (!c) { free(a); free(b); perror("realloc"); return 1; }
    a = c;

    for (size_t i = 0; i < m; i++) printf("%d ", a[i]);
    printf("\n");

    free(a); free(b);
}

Common Pitfalls

  • Casting malloc in C (unnecessary); ensure <stdlib.h> is included.
  • Losing the original pointer when realloc fails; always assign to a temporary.
  • Double free and use-after-free.
  • Not checking for integer overflow when computing sizes.

Summary

Allocate with malloc/calloc, resize carefully with realloc, and always free exactly once.

Real-Time Use Cases

  • Dynamic Data Structures: Implementing linked lists, trees, graphs, and other structures where the size is not known at compile time.
  • // Linked list node example
    #include <stdlib.h>
    struct Node {
        int data;
        struct Node* next;
    };
    struct Node* head = (struct Node*)malloc(sizeof(struct Node));
    head->data = 10;
    head->next = NULL;
    free(head);
    
  • Buffer Management: Allocating buffers for file I/O, network communication, or image processing where data size varies.
  • // Dynamic buffer allocation for file reading
    #include <stdio.h>
    #include <stdlib.h>
    FILE *f = fopen("data.txt", "r");
    char *buffer = (char*)malloc(1024);
    fgets(buffer, 1024, f);
    fclose(f);
    free(buffer);
    
  • Plugin Systems: Loading and unloading modules or plugins at runtime, requiring dynamic memory allocation for resources.
  • // Simulating plugin resource allocation
    void* plugin_data = malloc(256); // Allocate memory for plugin
    // ... use plugin_data ...
    free(plugin_data); // Release when plugin is unloaded
    
  • Game Development: Managing entities, assets, or levels that are created and destroyed during gameplay.
  • // Dynamic array for game entities
    int entity_count = 5;
    int *entities = (int*)malloc(entity_count * sizeof(int));
    // ... use entities ...
    free(entities);
    
  • Operating Systems: Kernel memory management, process control blocks, and resource allocation.
  • // Simulated process control block allocation
    struct PCB {
        int pid;
        // ... other fields ...
    };
    struct PCB *pcb = (struct PCB*)malloc(sizeof(struct PCB));
    pcb->pid = 1234;
    free(pcb);