|
|
|
Lecture 16 — memory management, hw5
|
|
|
|
|
how do malloc and free work?
|
|
|
|
|
OS
|
|
|
|
|
operating system provides system calls
|
|
|
|
|
a system call is a function programs use to request things from the operating system
|
|
|
|
|
these handle large chunks of contiguous memory
|
|
|
|
|
for example brk and sbrk in Linux
|
|
|
|
|
both modify the size of the heap, giving a program more or less memory to work with
|
|
|
|
|
this is clumsy and very low-level, which is why the C standard library give us nicer functions to work with
|
|
|
|
|
free list
|
|
|
|
|
the data structure you will use in hw5 to support your versions of malloc and free
|
|
|
|
|
linked list of available blocks of memory
|
|
|
|
|
each block knows its size and the location of the next block
|
|
|
|
|
blocks kept in order of ascending memory address
|
|
|
|
|
for each request, scan down the list for a block large enough to fulfill the request
|
|
|
|
|
remove the block from the list and return it
|
|
|
|
|
what if the block is much larger than the request?
|
|
|
|
|
split the block in two, returning one of appropriate size
|
|
|
|
|
to free a block, find where it should go in the list by memory address and insert it
|
|
|
|
|
combine it with previous and next blocks if they are adjacent
|
|
|
|
|
important to prevent fragmentation
|
|
|
|
|
How will we keep track of the size of a block?
|
|
|
|
|
struct free_block { uintptr_t size; struct free_block *next; };
|
|
|
|
|
each block will have a struct like this as a header
|
|
|
|
|
when we return a block, we’ll actually return a pointer to the part of the block past the header
|
|
|
|
|
this way, the header will still be intact when the block is freed
|
|
|
|
|
where will your free list get its initial memory? How will your free list get more memory if it doesn’t have a big enough block?
|
|
|
|
|
malloc
|
|
|
|
|
getmem
|
|
|
|
|
block addresses made up to be convenient rather than realistic
|
|
|
|
|
example: request 100 bytes block0 @ 0x000, size 32 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes
|
|
|
|
|
block1 is returned, no splitting needed: block0 @ 0x000, size 32 bytes block1 @ 0x110, size 64 bytes
|
|
|
|
|
address returned: 0x080
|
|
|
|
|
exercise: request 10 bytes block0 @ 0x000, size 64 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes
|
|
|
|
|
block0 @ 0x020, size 32 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes or block0 @ 0x000, size 32 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes
|
|
|
|
|
block0 can be split two different ways
|
|
|
|
|
address returned: 0x010 or 0x040
|
|
|
|
|
exercise: request 200 bytes block0 @ 0x0000, size 64 bytes block1 @ 0x0700, size 112 bytes block2 @ 0x8000, size 64 bytes
|
|
|
|
|
block0 @ 0x0000, size 64 bytes block1 @ 0x0700, size 112 bytes block3 @ 0x1000, size 3872 bytes block2 @ 0x8000, size 64 bytes
|
|
|
|
|
new 4-kilobyte (4096-byte) block of memory allocated via malloc (arbitrarily assumed address of 0x1000), placed in the appropriate position in the list, and then split to satisfy the request
|
|
|
|
|
freemem
|
|
|
|
|
block addresses made up to be convenient rather than realistic
|
|
|
|
|
example: freeing 0x040 (block @ 0x030, size 32 bytes) block0 @ 0x000, size 32 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes
|
|
|
|
|
block0 @ 0x000, size 32 bytes block @ 0x030, size 32 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes coalesce to get block0 @ 0x000, size 80 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes
|
|
|
|
|
0x000 + 0x10 (for header) + 0x20 (size of block0) = 0x030, so we combine block0 and block
|
|
|
|
|
0x000 + 0x10 + 0x50 = 0x060, so we don’t need to combine block0 and block1
|
|
|
|
|
exercise: freeing 0x100 (block @ 0x0f0, size 16 bytes) block0 @ 0x000, size 32 bytes block1 @ 0x070, size 112 bytes block2 @ 0x110, size 64 bytes
|
|
|
|
|
block0 @ 0x000, size 32 bytes block1 @ 0x070, size 224 bytes
|
|
|
|
|
0x070 + 0x10 (for header) + 0x70 (size of block1) = 0x0f0, so we combine block1 and block
|
|
|
|
|
0x070 + 0x10 (for header) + 0x90 (size of block0) = 0x110, so we combine block1 and block2
|
|
|
|
|
could combine these in either order
|
|
|
|
|
future topics
|
|
|
|
|
lecture going over midterm?
|
|
|
|
|
stack smashing
|
|
|
|
|
testing
|
|
|
|
|
C++
|
|
|
|
|
concurrency
|
|
|