Chapter 13: Storage
Level 2 — Cognition
malloc, storage duration, initialization -- how C manages object lifetimes and how Auto makes it automatic.
Memory management is where C programs most often go wrong. Memory leaks, use-after-free, double-free, and dangling pointers account for a large fraction of C's security vulnerabilities. This chapter examines C's storage mechanisms and shows how Auto eliminates entire categories of memory errors.
13.1 malloc and Friends
C provides four functions for dynamic memory allocation:
// C Deep Dive: dynamic allocation
void *malloc(size_t size); // allocate size bytes (uninitialized)
void *calloc(size_t n, size_t s); // allocate n*s bytes (zero-initialized)
void *realloc(void *p, size_t s); // resize allocation (may move)
void free(void *p); // deallocateTypical usage in C:
// C Deep Dive: malloc lifecycle
int *arr = malloc(10 * sizeof(int)); // allocate
if (!arr) { /* handle error */ } // check NULL
for (int i = 0; i < 10; i++) {
arr[i] = i * i; // use
}
// ... later ...
free(arr); // deallocate
arr = NULL; // avoid dangling pointerThe problems are legion:
- Forgetting to free: memory leaks that grow over time.
- Using after free: undefined behavior, often exploitable.
- Double free: corrupts the heap allocator's internal state.
- Not checking NULL: dereferencing a failed allocation crashes.
- Wrong size:
malloc(sizeof(int*))when you meantmalloc(sizeof(int)).
Auto's replacement: automatic storage. Auto manages object lifetimes automatically. There is no malloc, free, realloc, or calloc in Auto:
// Auto: no malloc/free, automatic lifetime management
var arr [10]int
for i in 0..10 {
arr[i] = i * i
}
print("First:", arr[0])
// no free needed -- storage reclaimed automaticallyWhen Auto needs dynamically-sized collections, the standard library provides growable containers with automatic cleanup:
// Auto: growable buffer
type Buffer {
data [256]int
size int
}
fn Buffer.new() Buffer {
Buffer([256]int{}, 0)
}
fn Buffer.push(b Buffer, val int) {
if b.size < 256 {
b.data[b.size] = val
b.size = b.size + 1
}
}