Understanding Storage Duration, Dynamic Memory, and Building a Custom Vector in C

Storage Duration Categories

In C, objects have specific lifetimes determined by their storage duration. There are three primary types:

  • Static Storage Duration: Variables declared outside functions or with static inside functions. They exist for the entire program execution.
  • Automatic Storage Duration: Local variables (typically on the stack). They exist only while the enclosing function is executing.
  • Allocated Storage Duration: Memory requested dynamical (typically on the heap) via functions like malloc. It exists until explicitly freed by free.

Stack vs. Heap Usage

Stack Scenarios

The stack is ideal for small, temporary variables with a known size and a short lifecycle, such as function parameters, loop counters, and local arrays (if small). Allocation and deallocation are handled automatically.

Heap Scenarios

The heap is necessary when you need to allocate memory whose size is not known at compile time, or when the data must persist beyond the scope of the function that created it. This is common for dynamic arrays, linked lists, and complex data structures.

Type Conversions

When dealing with pointers and memory allocation, explicit casting is sometimes required (though not strictly necessary in standard C for void * assignments), and understanding integer to pointer conversions is crucial for low-level manipulation.

Memory Leaks

A memory leak occurs when dynamically allocated memory is no longer referenced by the program but has not been released. Over time, this can exhaust available memory. Always ensure every malloc, calloc, or realloc has a corresponding free.

Dynamic Memory Functions

free

The free function deallocates a block of memory previously allocated by malloc, calloc, or realloc.

malloc

malloc(size) allocates a contiguous block of memory of size bytes. The memory is uninitialized.

calloc

calloc(count, size) allocates memory for an array of count elements, each of size bytes, and initializes all bits to zero.

Failure Handling: If allocation fails, these functionss return NULL. Always check the return value before usage.

realloc

realloc(ptr, new_size) attempts to resize the memory block pointed to by ptr to new_size. A common safe pattern is to use a temporary pointer to avoid losing the original pointer if reallocation fails.

Implementing a Dynamic Array (Vector)

We will implement a generic-like vector structure. We use header guards to prevent multiple inclusions.

array_list.h

#ifndef ARRAY_LIST_H
#define ARRAY_LIST_H

// Define the data type stored in the list
typedef char* ItemType;

typedef struct {
    ItemType* elements;
    int current_count;
    int max_capacity;
} ArrayList;

// Lifecycle management
ArrayList* list_init(void);
void list_free(ArrayList* list);

// Modification operations
void list_append(ArrayList* list, ItemType item);
void list_prepend(ArrayList* list, ItemType item);
void list_insert_at(ArrayList* list, ItemType item, int position);

#endif

array_list.c

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

#define INIT_SIZE 10
#define GROWTH_LIMIT 1000

void expand_list(ArrayList* list) {
    int old_cap = list->max_capacity;
    int new_cap;
    
    if (old_cap <= GROWTH_LIMIT) {
        new_cap = old_cap * 2;
    } else {
        new_cap = old_cap + (old_cap / 2);
    }

    ItemType* temp = realloc(list->elements, new_cap * sizeof(ItemType));
    if (temp == NULL) {
        fprintf(stderr, "Memory reallocation failed in expand_list\n");
        exit(EXIT_FAILURE);
    }
    list->elements = temp;
    list->max_capacity = new_cap;
}

ArrayList* list_init() {
    ArrayList* list = calloc(1, sizeof(ArrayList));
    if (list == NULL) {
        perror("Failed to allocate ArrayList structure");
        return NULL;
    }

    list->elements = calloc(INIT_SIZE, sizeof(ItemType));
    if (list->elements == NULL) {
        perror("Failed to allocate element array");
        free(list);
        return NULL;
    }

    list->max_capacity = INIT_SIZE;
    list->current_count = 0;
    return list;
}

void list_free(ArrayList* list) {
    if (list == NULL) return;
    free(list->elements);
    free(list);
}

void list_append(ArrayList* list, ItemType item) {
    if (list->current_count >= list->max_capacity) {
        expand_list(list);
    }
    list->elements[list->current_count++] = item;
}

void list_prepend(ArrayList* list, ItemType item) {
    if (list->current_count >= list->max_capacity) {
        expand_list(list);
    }
    // Shift elements to the right
    for (int i = list->current_count; i > 0; i--) {
        list->elements[i] = list->elements[i - 1];
    }
    list->elements[0] = item;
    list->current_count++;
}

void list_insert_at(ArrayList* list, ItemType item, int position) {
    if (position < 0 || position > list->current_count) return;
    
    if (list->current_count >= list->max_capacity) {
        expand_list(list);
    }
    // Shift elements to the right starting from the insertion point
    for (int i = list->current_count; i > position; i--) {
        list->elements[i] = list->elements[i - 1];
    }
    list->elements[position] = item;
    list->current_count++;
}

demo_main.c

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

int main() {
    ArrayList* my_list = list_init();
    
    for (int i = 1; i <= 100; i++) {
        char* buffer = calloc(i + 1, sizeof(char));
        if (buffer == NULL) {
            fprintf(stderr, "Allocation failed in main loop\n");
            return 1;
        }
        for (int j = 0; j < i; j++) {
            buffer[j] = '0' + (j % 10);
        }
        list_append(my_list, buffer);
    }

    for (int i = 0; i < my_list->current_count; i++) {
        printf("%s\n", my_list->elements[i]);
    }

    // Cleanup: Free the strings inside the list first
    for (int i = 0; i < my_list->current_count; i++) {
        free(my_list->elements[i]);
    }
    
    list_free(my_list);
    return 0;
}

Tags: c programming dynamic memory allocation malloc realloc Data Structures

Posted on Sun, 09 Aug 2026 16:25:28 +0000 by jannoy