CS 208 s21 — C: Memory Management
Table of Contents
1 Allocating Memory
There are two ways that memory gets allocated for data storage:
- Compile Time (or static) Allocation
- Memory for named variables is allocated by the compiler
- Exact size and type of storage must be known at compile time
- For standard array declarations, this is why the size has to be constant
- Dynamic Memory Allocation
- Memory allocated "on the fly" during run time
- Dynamically allocated space usually placed in a program segment known as the heap or the free store
- Exact amount of space or number of items does not have to be known by the compiler in advance.
- For dynamic memory allocation, pointers are crucial
2 Dynamic Memory Allocation
- We can dynamically allocate storage space while the program is running, but we cannot create new variable names "on the fly"
- For this reason, dynamic allocation requires two steps:
- Creating the dynamic space.
- Storing its address in a pointer (so that the space can be accesed)
- To dynamically allocate memory in C, we use the
malloc
function provided bystdlib.h
malloc
takes in a number of bytes to allocate and returns a pointer to the newly allocated spacemalloc
does not do any initialization, so the contents of this memory can be whatever was last written to those bytes- this means you must always perform initialization on memory return by
malloc
- this means you must always perform initialization on memory return by
- De-allocation:
- Deallocation is the "clean-up" of space being used for variables or other data storage
- Compile time variables are automatically deallocated based on their known extent
- It is the programmer's job to deallocate dynamically created space
- To de-allocate dynamic memory, we use the
free
function operatorfree
takes a pointer that was previously returned bymalloc
and makes that memory available for future allocationfree
has undefined behavior is used with a pointer that wasn't returned bymalloc
or a pointer that was already freed
3 Memory Layout
Though memory is a long array of bytes, it is actually separated into various segments or memory regions. Memory allocated at compile time is located on the stack, which resides at high addresses in memory. As more data is added to the stack, the region grows to include lower addresses, so we say the stack grows down.
Memory allocated dynamically using malloc
is placed on the heap, which resides somewhere in the middle of memory.
As more data is added to the heap, the region grows to include higher addresses, so we say the heap grows up.
The other three regions (static data, literals, and instructions) are fixed in size and get initialized when a program starts running.