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)

  1. 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.
  2. 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.
  3. 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.
  4. 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.