Answers to Question 3 (18 points, 30 minutes)
Part 1 (12 points)
You'll note that this part was lifted verbatim from the test two years
ago. I'll lift the answer too:
malloc() acts as an interface to sbrk(), handling memory
allocation with a free-list implementation. At all times, a list of
chunks of free memory is maintained using a global variable.
Initially, this list is empty. The list is implemented so that the
first 12 bytes of each chunk contains the node information -- a
forward pointer, a backward pointer, and the size of the chunk. When
malloc(n) is called, a chunk of at least k bytes is
sought on the list, where k is eight plus n, padded to a
multiple of eight. If no such chunk is found, sbrk() is called
th to allocate a new huge chunk (i.e. 8K or so). Once a chunk is
found, it is either broken into two pieces -- k and the
remainder -- or kept whole if the remainder is under 12 bytes. The
size k chunk is returned to the user, and the remainder is put
onto the free list. The first 8 bytes of the k-sized chunk are
initialized to contain the chunk size (k) and perhaps a checksum.
A pointer to the 8th byte is returned to the user (giving him/her at
least) n bytes aligned on an 8-byte quantity.
When free(x) is called, the chunk is put back onto the
free-list. It knows the size of the chunk is at the address x-8.
If the chunks adjacent to the newly freed chunks are also
free, free() should coalesce them to minimize external
fragmentation.
Grading
I took off points if you missed important
things like where the size was kept, how free()
found this size, etc.
Part 2 (6 points)
-
The user has called malloc(sizeof(int253)) 1024 times, and then called
free() twice. That means he thinks he has allocated
253*4*1024 - 253*4*2 = 1,034,264 bytes. This is equal to
253*4*1022 or 1012*1022.
- malloc() has been called 1024 times, and free() twice.
Thus, there are 1022 malloc()'d chunks of memory, each of which
has eight bytes of bookkeeping. Thus there are 1022*8 = 8176
bytes of bookkeeping.
- sizeof(int253) is 253*4 = 1012. This is a multiple
of four, but not of eight. Therefore, each malloc() call will add
4 bytes of padding, for a total of 1022*4 = 4088 bytes.
- Conveniently, 253*4 + 8 + 4 = 1024, which means that
each chunk allocated by malloc() is 1024 bytes. If we assume
that malloc() calls sbrk() in 8K chunks, then sbrk()
is called every eight malloc()'s. Since malloc() is called
1024 times, and 1024 is a multiple of 8, there are no chunks in the
free list at the end of the for loop. The two free()
calls free up two 1024-byte chunks, meaning that there are 2048
bytes in the free list.
This adds up to a total of 1022 * (253*4 + 8 + 4) + 2048 =
1,048,576 bytes. This is exactly one megabyte.
Grading
You started with 6 points, and I took off points for bad assumptions or
math.