ProgrammingEmbedded C Developer

How does memory management work in C when dealing with arrays, structures, and pointers? How to avoid memory leaks and data corruption?

Pass interviews with Hintsage AI assistant

Answer.

Background

In C, the programmer directly manages memory: the allocation, deallocation, and usage of arrays, structures, and pointers are controlled manually. The mechanism for dynamic memory allocation has existed in C since the 1970s and is implemented through special functions from the standard library (malloc, calloc, realloc, free). This approach provides performance and flexibility but requires carefulness.

Problem

Errors in memory management can lead to leaks, corruption of other data, program crashes, or security vulnerabilities. Common mistakes include forgotten free calls, array out-of-bounds accesses, incorrect pointer typecasting, or double freeing memory. The situation is analogous for structures, but the risk of forgetting to clean up nested dynamic fields is added.

Solution

To minimize errors, it is recommended to develop strictly structured code, track all allocations and deallocations of memory, avoid using freed pointers, and monitor the sizes of allocated arrays. It is important to use static analysis tools, final checks (valgrind, sanitizers), and to adhere to agreements: whoever called malloc should also free the memory.

Code Example:

#include <stdio.h> #include <stdlib.h> typedef struct { int *arr; size_t size; } ArrayWrapper; ArrayWrapper *create(size_t n) { ArrayWrapper *aw = malloc(sizeof(ArrayWrapper)); if (!aw) return NULL; aw->arr = malloc(sizeof(int) * n); if (!aw->arr) { free(aw); return NULL; } aw->size = n; return aw; } void destroy(ArrayWrapper *aw) { if (aw) { free(aw->arr); free(aw); } }

Key Features:

  • Dynamic arrays and structures can be created at any size at runtime.
  • The code that obtained the allocated memory is responsible for it.
  • The key to safety is to free memory immediately after use, avoiding double freeing.

Tricky Questions.

What happens when freeing memory with a null pointer (free(NULL))?

According to the C standard, calling free on a null pointer is safe — nothing happens, no error occurs. This is convenient for transferring responsibility for freeing memory.

Can memory be used after calling free?

No, using memory after it has been freed (use-after-free) is a classic error. The data may change or the area may be allocated to another process. Pointers should always be nullified after free.

int *ptr = malloc(10); free(ptr); ptr = NULL; // Safely

Is it mandatory to free all allocated memory before exiting a program?

Technically, it is not necessary — the OS frees all resources upon program exit. However, ignoring memory cleanup is an anti-pattern that complicates debugging and leads to errors in large, long-running programs.

Common Mistakes and Anti-Patterns

  • Losing a pointer to allocated memory (memory leak).
  • Double freeing memory, use-after-free.
  • Incorrect size of allocated memory (sizeof incorrect type).

Real-life Example

Negative Case

A developer creates dynamic arrays within a function but forgets to clean them up:

Pros:

  • Quick implementation, no errors with small volumes.

Cons:

  • Memory leaks with large data, program crashes, irreparable bugs.

Positive Case

All code is checked by a static analyzer, all pointers are nullified after free, each malloc is paired with free:

Pros:

  • Easy maintenance, low bug probability.

Cons:

  • Slightly larger code size.