Claude
Skills
Sign in
Back

c-memory-management

Included with Lifetime
$97 forever

Use when managing memory in C programs with malloc/free, pointers, and avoiding common memory safety pitfalls.

General

What this skill does


# C Memory Management

Master manual memory management in C with proper allocation, deallocation,
pointer handling, and techniques to avoid memory leaks and corruption.

## Overview

C requires manual memory management through explicit allocation and
deallocation. Understanding pointers, the heap, and proper memory handling is
crucial for writing safe and efficient C programs.

## Installation and Setup

### Compiler and Tools

```bash
# Install GCC compiler
# macOS
xcode-select --install

# Linux (Ubuntu/Debian)
sudo apt-get install build-essential

# Check installation
gcc --version

# Memory debugging tools
# Install Valgrind (Linux)
sudo apt-get install valgrind

# Install Address Sanitizer (built into GCC/Clang)
gcc -fsanitize=address -g program.c -o program
```

### Compilation Flags

```bash
# Basic compilation
gcc program.c -o program

# With warnings and debugging
gcc -Wall -Wextra -g program.c -o program

# With Address Sanitizer
gcc -fsanitize=address -g program.c -o program

# With optimization
gcc -O2 -Wall program.c -o program
```

## Core Patterns

### 1. Dynamic Memory Allocation

```c
// malloc - allocate memory
#include <stdlib.h>
#include <string.h>

int* allocate_array(size_t size) {
    int* arr = malloc(size * sizeof(int));
    if (arr == NULL) {
        return NULL;  // Allocation failed
    }
    return arr;
}

// calloc - allocate and zero-initialize
int* allocate_zeroed_array(size_t size) {
    int* arr = calloc(size, sizeof(int));
    if (arr == NULL) {
        return NULL;
    }
    return arr;
}

// realloc - resize allocation
int* resize_array(int* arr, size_t old_size, size_t new_size) {
    int* new_arr = realloc(arr, new_size * sizeof(int));
    if (new_arr == NULL && new_size > 0) {
        // Reallocation failed, original array still valid
        return NULL;
    }
    return new_arr;
}

// free - deallocate memory
void cleanup_array(int** arr) {
    if (arr != NULL && *arr != NULL) {
        free(*arr);
        *arr = NULL;  // Prevent dangling pointer
    }
}
```

### 2. Pointer Basics

```c
// Pointer declaration and usage
void pointer_basics() {
    int value = 42;
    int* ptr = &value;  // ptr points to value
    
    printf("Value: %d\n", value);
    printf("Address: %p\n", (void*)&value);
    printf("Pointer: %p\n", (void*)ptr);
    printf("Dereferenced: %d\n", *ptr);
    
    *ptr = 100;  // Modify through pointer
    printf("New value: %d\n", value);
}

// Null pointers
void null_pointer_check(int* ptr) {
    if (ptr == NULL) {
        printf("Null pointer\n");
        return;
    }
    printf("Valid pointer: %d\n", *ptr);
}

// Pointer arithmetic
void pointer_arithmetic() {
    int arr[] = {10, 20, 30, 40, 50};
    int* ptr = arr;
    
    for (int i = 0; i < 5; i++) {
        printf("%d ", *(ptr + i));  // Same as ptr[i]
    }
    printf("\n");
}
```

### 3. Dynamic Strings

```c
#include <string.h>

// Create string copy
char* string_duplicate(const char* str) {
    if (str == NULL) {
        return NULL;
    }
    
    size_t len = strlen(str);
    char* copy = malloc(len + 1);  // +1 for null terminator
    
    if (copy != NULL) {
        strcpy(copy, str);
    }
    
    return copy;
}

// String concatenation
char* string_concat(const char* s1, const char* s2) {
    if (s1 == NULL || s2 == NULL) {
        return NULL;
    }
    
    size_t len1 = strlen(s1);
    size_t len2 = strlen(s2);
    
    char* result = malloc(len1 + len2 + 1);
    if (result == NULL) {
        return NULL;
    }
    
    strcpy(result, s1);
    strcat(result, s2);
    
    return result;
}

// Safe string functions
char* safe_string_copy(const char* src, size_t max_len) {
    if (src == NULL) {
        return NULL;
    }
    
    size_t len = strnlen(src, max_len);
    char* dest = malloc(len + 1);
    
    if (dest != NULL) {
        memcpy(dest, src, len);
        dest[len] = '\0';
    }
    
    return dest;
}
```

### 4. Structures and Memory

```c
// Structure with dynamic members
typedef struct {
    char* name;
    int* scores;
    size_t num_scores;
} Student;

Student* create_student(const char* name, size_t num_scores) {
    Student* student = malloc(sizeof(Student));
    if (student == NULL) {
        return NULL;
    }
    
    student->name = string_duplicate(name);
    if (student->name == NULL) {
        free(student);
        return NULL;
    }
    
    student->scores = malloc(num_scores * sizeof(int));
    if (student->scores == NULL) {
        free(student->name);
        free(student);
        return NULL;
    }
    
    student->num_scores = num_scores;
    memset(student->scores, 0, num_scores * sizeof(int));
    
    return student;
}

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

### 5. Memory Pools

```c
// Simple memory pool
typedef struct {
    void* pool;
    size_t block_size;
    size_t num_blocks;
    size_t next_free;
} MemoryPool;

MemoryPool* create_pool(size_t block_size, size_t num_blocks) {
    MemoryPool* pool = malloc(sizeof(MemoryPool));
    if (pool == NULL) {
        return NULL;
    }
    
    pool->pool = malloc(block_size * num_blocks);
    if (pool->pool == NULL) {
        free(pool);
        return NULL;
    }
    
    pool->block_size = block_size;
    pool->num_blocks = num_blocks;
    pool->next_free = 0;
    
    return pool;
}

void* pool_allocate(MemoryPool* pool) {
    if (pool == NULL || pool->next_free >= pool->num_blocks) {
        return NULL;
    }
    
    void* block = (char*)pool->pool + (pool->next_free * pool->block_size);
    pool->next_free++;
    
    return block;
}

void destroy_pool(MemoryPool** pool) {
    if (pool == NULL || *pool == NULL) {
        return;
    }
    
    free((*pool)->pool);
    free(*pool);
    *pool = NULL;
}
```

### 6. Reference Counting

```c
// Reference counted string
typedef struct {
    char* data;
    size_t ref_count;
} RefString;

RefString* refstring_create(const char* str) {
    RefString* rs = malloc(sizeof(RefString));
    if (rs == NULL) {
        return NULL;
    }
    
    rs->data = string_duplicate(str);
    if (rs->data == NULL) {
        free(rs);
        return NULL;
    }
    
    rs->ref_count = 1;
    return rs;
}

RefString* refstring_retain(RefString* rs) {
    if (rs != NULL) {
        rs->ref_count++;
    }
    return rs;
}

void refstring_release(RefString** rs) {
    if (rs == NULL || *rs == NULL) {
        return;
    }
    
    (*rs)->ref_count--;
    
    if ((*rs)->ref_count == 0) {
        free((*rs)->data);
        free(*rs);
    }
    
    *rs = NULL;
}
```

### 7. Memory Debugging

```c
// Debug wrapper for malloc
#ifdef DEBUG_MEMORY
typedef struct {
    void* ptr;
    size_t size;
    const char* file;
    int line;
} AllocationInfo;

static AllocationInfo allocations[1000];
static size_t num_allocations = 0;

void* debug_malloc(size_t size, const char* file, int line) {
    void* ptr = malloc(size);
    if (ptr != NULL && num_allocations < 1000) {
        allocations[num_allocations].ptr = ptr;
        allocations[num_allocations].size = size;
        allocations[num_allocations].file = file;
        allocations[num_allocations].line = line;
        num_allocations++;
    }
    return ptr;
}

void debug_free(void* ptr) {
    for (size_t i = 0; i < num_allocations; i++) {
        if (allocations[i].ptr == ptr) {
            allocations[i] = allocations[num_allocations - 1];
            num_allocations--;
            break;
        }
    }
    free(ptr);
}

void print_leaks() {
    printf("Memory leaks: %zu\n", num_allocations);
    for (size_t i = 0; i < num_allocations; i++) {
        printf("  %p (%zu bytes) at %s:%d\n",
               allocations[i].ptr,
               allocations[i].size,
               allocations[i].file,
               allocations[i].line);
    }
}

#define malloc(size) debug_malloc(size, __FI

Related in General