09 Memory
09 Memory
Alan L. Cox
[email protected]
Heap Memory
Unused
0x00000000
Cox Dynamic Memory Allocation 6
Malloc Package
#include <stdlib.h>
void *malloc(size_t size)
If successful:
• Returns a pointer to a memory block of at least size bytes,
aligned to at least an 8-byte boundary
• If size == 0, returns NULL (or a unique pointer)
If unsuccessful: returns NULL (0)
void free(void *ptr)
Returns the block pointed at by ptr to pool of available
memory
ptr must come from a previous call to malloc or realloc
void *realloc(void *ptr, size_t size)
Changes size of block pointed at by ptr and returns
pointer to new block
Contents of new block unchanged up to the minimum of
the old and new sizes
Free word
Allocated block Free block
(4 words) (3 words) Allocated word
p1 = malloc(4*sizeof(int))
p2 = malloc(5*sizeof(int))
p3 = malloc(6*sizeof(int))
free(p2)
p4 = malloc(2*sizeof(int))
Allocators:
Can’t control number or size of allocated blocks
Must respond immediately to all allocation requests
• i.e., can’t reorder or buffer requests
Must allocate blocks from free memory
• i.e., can only place allocated blocks in free memory
Must align blocks so they satisfy all alignment
requirements
• e.g., 8-byte alignment for libc malloc on some systems
Can only manipulate and modify free memory
Can’t move the allocated blocks once they are allocated
• i.e., compaction is not allowed
Throughput:
Number of completed requests per unit time
Example:
• 5,000 malloc calls and 5,000 free calls in 10 seconds
• Throughput is 1,000 operations/second
Internal Internal
payload fragmentation
fragmentation
p2 = malloc(5*sizeof(int))
p3 = malloc(6*sizeof(int))
free(p2)
p4 = malloc(7*sizeof(int))
oops!
External fragmentation depends on the pattern of future
requests, and thus is difficult to measure
Cox Dynamic Memory Allocation 16
Dynamic Memory Allocation
(Video #1)
Alan L. Cox
[email protected]
Free word
Allocated block Free block
(4 words) (3 words) Allocated word
p0
free(p0)
p1 = malloc(1)
Standard method
Keep the length of a block in the word preceding
the block.
• This word is often called the header field or header
Requires an extra word for every allocated block
p0 = malloc(4 * sizeof(int)) p0
5 4 6 2
5 4 6 2
4 4 6 2
4 4 4 2 2
Cox Dynamic Memory Allocation 24
Implicit List: Freeing a Block
Simplest implementation:
Only need to clear allocated flag
• void free_block(ptr p) { *p = *p & ~0x1; }
But can lead to “false fragmentation”
4 4 4 2 2
free_block(p) p
4 4 4 2 2
malloc(5 * sizeof(int))
Oops!
There is enough free space, but the allocator won’t
be able to find it!
4 4 4 2 2
free_block(p) p
4 4 6 2
But how do we coalesce with previous block?
4 4 4 4 6 6 4 4
m1 1 m1 1
m1 1 m1 1
n 1 n 0
n 1 n 0
m2 1 m2 1
m2 1 m2 1
m1 1 m1 1
m1 1 m1 1
n 1 n+m2 0
n 1
m2 0
m2 0 n+m2 0
m1 0 n+m1 0
m1 0
n 1
n 1 n+m1 0
m2 1 m2 1
m2 1 m2 1
m1 0 n+m1+m2 0
m1 0
n 1
n 1
m2 0
m2 0 n+m1+m2 0
Alan L. Cox
[email protected]
5 4 6 2
5 4 6 2
Forward links
A B
4 4 4 4 6 6 4 4 4 4
C
Back links
pred succ
pred succ
After:
(with splitting) free block
Case 2: a-a-f p s
Splice out next, coalesce
self and next, and add to before:
beginning of free list a self f
p s h
after:
a f
p s h
after:
f a
p1 s1 p2 s2
Case 4: f-a-f
Splice out prev and next, before:
coalesce with self, and add
f self f
to beginning of list
p1 s1 p2 s2 h
after:
f
Cox Dynamic Memory Allocation 42
Explicit List: Summary
5 4 6 2
5 4 6 2
5-8
9-16
5 4 6 2
5 4 6 2
Changes API
malloc() and free()
must take a region
as an argument
Cox Dynamic Memory Allocation 52
Implementation Summary
Many options:
Data structures for keeping track of free blocks
Block choice policy
Splitting & coalescing policies
Alan L. Cox
[email protected]
Root nodes
unreachable
(garbage)
Overall idea
Maintain a free list of unallocated blocks
Maintain a count of the number of references to
each allocated block
To allocate, grab a sufficiently large block from the
free list
When a count goes to zero, deallocate it
a = cons(10,empty)
b = cons(20,a)
a = b
b = …
a = …
a = cons(10,empty) a 1 10
b = cons(20,a)
a = b
b = …
a = …
a = cons(10,empty) a 2 10
b = cons(20,a)
a = b
b = …
a = … b 1 20
a = cons(10,empty) 1 10
b = cons(20,a)
a = b
b = … a
a = … b 2 20
a = cons(10,empty) 1 10
b = cons(20,a)
a = b
b = … a
a = … 1 20
a = cons(10,empty) 1 10
b = cons(20,a)
a = b
b = …
a = … 0 20
a = cons(10,empty) 0 10
b = cons(20,a)
a = b
b = …
a = …
a = cons(10,empty)
b = cons(20,a)
a = b
b = …
a = …
Disadvantages:
Managing & testing counts is generally expensive
• Can optimize
Doesn’t work with cycles!
• Approach can be modified to work, with difficulty
Advantage:
Simple
• Easily adapted, e.g., for parallel or distributed GC
Overall idea
Maintain a free list of unallocated blocks
To allocate, grab a sufficiently large block from
free list
When no such block exists, GC
• Should find blocks & put them on free list
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Unmarked= Marked=
Root pointers:
Heap:
Free list:
Advantages:
No space overhead for reference counts
No time overhead for reference counts
Handles cycles
Disadvantage:
Noticeable pauses for GC
Overall idea:
Maintain From and To spaces in heap
To allocate, get sequentially next block in From
space
• No free list!
When From space full, GC into To space
• Swap From & To names
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Uncopied= Copied=
Root pointers:
From:
To:
Root pointers:
To:
From:
Advantages:
Only one pass over data
Only touches reachable data
Little space overhead per data item
Very simple allocation
“Compacts” data
Handles cycles
Disadvantages:
Noticeable pauses for GC
Double the basic heap size
Goal
Allow GC in C-like languages
Virtual Memory