Lecture 22: Dynamic Memory Allocation Advanced

31
Computer Systems Organization Mohamed Zahran (aka Z) [email protected] http://www.mzahran.com CSCI-UA.0201-003 Lecture 22: Dynamic Memory Allocation Advanced Slides adapted (and slightly modified) from: Clark Barrett Jinyang Li Randy Bryant Dave O’Hallaron

Transcript of Lecture 22: Dynamic Memory Allocation Advanced

Page 1: Lecture 22: Dynamic Memory Allocation Advanced

Computer Systems Organization

Mohamed Zahran (aka Z)

[email protected]

http://www.mzahran.com

CSCI-UA.0201-003

Lecture 22: Dynamic Memory Allocation Advanced

Slides adapted (and slightly modified) from: • Clark Barrett • Jinyang Li • Randy Bryant • Dave O’Hallaron

Page 2: Lecture 22: Dynamic Memory Allocation Advanced

Today

• Explicit free lists

• Segregated free lists

• Memory-related perils and pitfalls

Page 3: Lecture 22: Dynamic Memory Allocation Advanced

Explicit Free list • Disadvantage of implicit free list

– For each allocation, O(N) blocks are traversed, many of which are not free

• Explicit free list – Maintain list(s) of free blocks instead of all

blocks

– Need to store forward/back pointers in each free block, not just sizes

Page 4: Lecture 22: Dynamic Memory Allocation Advanced

Explicit Free Lists

Size

Payload and padding

a

Size a

Size a

Size a

Next

Prev

Allocated block Free block

Store next/prev pointers in “payload’’ of free block. Does this increase space overhead?

Page 5: Lecture 22: Dynamic Memory Allocation Advanced

Allocating From Explicit Free Lists

Free list

Free list after allocation

= malloc(…)

Page 6: Lecture 22: Dynamic Memory Allocation Advanced

Freeing With Explicit Free Lists

• Where in the free list to put a newly freed block? – Insert freed block at the beginning of the

free list (LIFO) • Pro: simple and constant time

– Insert freed blocks to maintain address order: addr(prev) < addr(curr) < addr(next) • Pro: may lead to less fragmentation than LIFO

Page 7: Lecture 22: Dynamic Memory Allocation Advanced

Freeing With LIFO: Basic case

• Insert the freed block at root

free( )

Root

Root

Check prev block’s footer and next block’s header for allocation status

Page 8: Lecture 22: Dynamic Memory Allocation Advanced

Freeing With LIFO: Coalesce

• Splice out prev block, coalesce, and insert new block at root

free( )

Root

Root

Page 9: Lecture 22: Dynamic Memory Allocation Advanced

Explicit List

Allocation is linear time in # of free blocks instead of all blocks

• Still expensive to find a free block that fits – How about keeping multiple linked lists of

different size classes?

Page 10: Lecture 22: Dynamic Memory Allocation Advanced

Today

• Explicit free lists

• Segregated free lists

• Memory-related perils and pitfalls

Page 11: Lecture 22: Dynamic Memory Allocation Advanced

Segregated List (Seglist) Allocators

• Multiple free lists each linking free blocks of similar sizes

• Often have separate classes for each small size • For larger sizes: One class for each two-power size

1-2

3

4

{5-8}

{9-inf}

Page 12: Lecture 22: Dynamic Memory Allocation Advanced

Seglist Allocator • Given an array of free lists, each one for

some size class

• To allocate a block of size n: – Search in appropriate free list containing size n – (optional) Split found block and place fragment

on appropriate list – try next larger class if no blocks found

• If no block is found: – Request additional heap memory from OS – Allocate block of n bytes from this new memory – Place remainder as a single free block in largest

size class.

Page 13: Lecture 22: Dynamic Memory Allocation Advanced

Seglist Allocator (cont.) • To free a block:

– Coalesce and place on appropriate list (optional)

• Advantages of seglist allocators – Fast allocation

– Better memory utilization • First-fit search of segregated free list

approximates a best-fit search of entire heap

Page 14: Lecture 22: Dynamic Memory Allocation Advanced

Today

• Explicit free lists

• Segregated free lists

• Memory-related perils and pitfalls

Page 15: Lecture 22: Dynamic Memory Allocation Advanced

Memory-Related Perils and Pitfalls

• Dereferencing bad pointers

• Reading uninitialized memory

• Overwriting memory

• Referencing nonexistent variables

• Freeing blocks multiple times

• Referencing freed blocks

• Failing to free blocks

Page 16: Lecture 22: Dynamic Memory Allocation Advanced

Dereferencing Bad Pointers • The classic scanf bug

int val;

...

scanf(“%d”, val);

Page 17: Lecture 22: Dynamic Memory Allocation Advanced

Reading Uninitialized Memory • Assuming that heap data is initialized to

zero

/* return y = Ax */

int *matvec(int **A, int *x) {

int *y = malloc(N*sizeof(int));

int i, j;

for (i=0; i<N; i++)

for (j=0; j<N; j++)

y[i] += A[i][j]*x[j];

return y;

}

Page 18: Lecture 22: Dynamic Memory Allocation Advanced

Overwriting Memory • Allocating the (possibly) wrong-sized

object

int **p;

p = malloc(N*sizeof(int));

for (i=0; i<N; i++) {

p[i] = malloc(M*sizeof(int));

}

Page 19: Lecture 22: Dynamic Memory Allocation Advanced

Overwriting Memory • Not checking the max string size

• Basis for classic buffer overflow attacks

char s[8];

int i;

gets(s); /* reads “123456789” from stdin */

Page 20: Lecture 22: Dynamic Memory Allocation Advanced

Overwriting Memory • Misunderstanding pointer arithmetic

int *search(int *p, int val) {

while (*p && *p != val)

p += sizeof(int);

return p;

}

Page 21: Lecture 22: Dynamic Memory Allocation Advanced

Referencing Nonexistent Variables

• Forgetting that local variables disappear when a function returns int *foo () {

int val;

return &val;

}

void main() {

int *p;

p = foo();

*p = 5;

}

Page 22: Lecture 22: Dynamic Memory Allocation Advanced

Freeing Blocks Multiple Times • Nasty!

x = malloc(N*sizeof(int));

<manipulate x>

free(x);

y = malloc(M*sizeof(int));

<manipulate y>

free(x);

Page 23: Lecture 22: Dynamic Memory Allocation Advanced

Referencing Freed Blocks • Evil!

x = malloc(N*sizeof(int));

<manipulate x>

free(x);

...

y = malloc(M*sizeof(int));

for (i=0; i<M; i++)

y[i] = x[i]++;

Page 24: Lecture 22: Dynamic Memory Allocation Advanced

Failing to Free Blocks (Memory Leaks)

• Slow, long-term killer!

foo() {

int *x = malloc(N*sizeof(int));

...

return;

}

Page 25: Lecture 22: Dynamic Memory Allocation Advanced

Failing to Free Blocks (Memory Leaks)

• Freeing only part of a data structure struct list {

int val;

struct list *next;

};

foo() {

struct list *head = malloc(sizeof(struct list));

head->val = 0;

head->next = NULL;

<create and manipulate the rest of the list>

...

free(head);

return;

}

Page 26: Lecture 22: Dynamic Memory Allocation Advanced

Dealing With Memory Bugs • Conventional debugger (gdb)

– Good for finding bad pointer dereferences – Hard to detect the other memory bugs

• Debugging malloc (dmalloc)

– Wrapper around conventional malloc – Detects memory bugs at malloc and free

boundaries – Cannot detect all memory bugs

• Overwrites into the middle of allocated blocks

• Freeing block twice that has been reallocated in the interim

• Referencing freed blocks

Page 27: Lecture 22: Dynamic Memory Allocation Advanced

Dealing With Memory Bugs (cont.) • Some malloc implementations contain

checking code

• Binary translator: valgrind (Linux), Purify – Rewrites text section of executable object file

– Can detect all errors as dmalloc

– Can also check each individual reference at runtime • Bad pointers

• Overwriting

• Referencing outside of allocated block

Page 28: Lecture 22: Dynamic Memory Allocation Advanced

A Word About Garbage Collection

• In C, it is the programmer’s responsibility to free any memory allocated by malloc/calloc/… .

• A garbage collection is a dynamic storage allocator that automatically frees allocated blocks that are no longer needed by the program.

• Allocated blocks that are no longer needed are called garbage.

Page 29: Lecture 22: Dynamic Memory Allocation Advanced

A Word About Garbage Collection

• In systems that support garbage collection (e.g. Java, Perl, Mathematica, …) – Applications explicitly allocate heap blocks

– But never free them!

• The garbage collector periodically identifies garbage and make appropriate calls to free.

How does the garbage collector recognizes blocks that are no longer needed?

Page 30: Lecture 22: Dynamic Memory Allocation Advanced

A Word About Garbage Collection

Root nodes

Heap nodes

Not-reachable (garbage)

Reachable

Reachabilty Graph Blocks in the heap

Blocks not in the heap

Page 31: Lecture 22: Dynamic Memory Allocation Advanced

Conclusions

• Dynamic memory allocator manages the heap.

• Dynamic memory allocator is part of the user-space

• The allocator has two main goals: reaching higher throughput (operations per second) and better memory utilization (i.e. reduces fragmentation).

• Section 9.9.12 is very useful