CS360 Final -- December 11, 1999. Question 1: Answer
and Grading
15 points
The answer
Your free() should do a few things:
- First, we could test to see that
ptr is a multiple of 8, and if not, dump core, but this
was not specified, so you didn't have to do it. My code below does do
it, but doing it or not doing it was not worth anything.
- Next, it should back up 8 bytes and turn that pointer into a Fnode.
Then it should test the checksum to see if it is ok.
- Next, it should check the size field -- subtract one and make sure that
it is a multiple of 8 and at least 16 bytes in size. If it is less
than 16 bytes, then we can't turn it into a FNode.
- Now we can free it. We do not need to modify the checksum, but we should
modify the size if we have not done so already by subtracting one.
Finally, we hook it onto the free list.
Sorry, I had a typo in the definition of FNode. The below definition
is correct. I'm not sure if anyone noticed (it said struct freelist
*flink instead of struct fnode *flink. Same with blink).
typedef struct fnode {
int checksum;
int size;
struct fnode *flink;
struct fnode *blink;
} FNode;
extern FNode *Freelist;
#define DUMP_CORE { char *p = (char *) 0; *p = 0; }
void free(void *ptr)
{
char *p;
FNode *fn;
p = (char *) ptr;
/* Test to see if ptr is a multiple of 8: */
if ( ((int)ptr) % 8 != 0) {
fprintf(stderr, "free() not given a multilpe of 8\n");
DUMP_CORE;
}
fn = (FNode *) ptr;
fn -= 2; /* Back up 8 bytes */
/* Test the checksum */
if ((int) fn != fn->checksum - 1) {
fprintf(stderr, "free(): Bad checksum\n");
DUMP_CORE;
}
/* Decrement the size and check it */
fn->size--;
if (fn->size < 16 || fn->size % 8 != 0) {
fprintf(stderr, "free(): Bad size\n");
DUMP_CORE;
}
/* Put fn onto the head of the freelist. */
fn->blink = NULL;
fn->flink = Freelist;
if (fn->flink != NULL) fn->flink->blink = fn;
Freelist = fn;
return;
}
Grading:
I was surprised at how badly the majority of you did on this
question. You did write free() as part of Lab 6, so
I was surprised at the number of people who couldn't figure
out the types of pointers or do the pointer arithmetic. Make sure
you read the above answer and understand why it works.
Also, when I say ``dump core'', that means make it dump core --
don't call exit(1).
Two more things -- I defined the linked list structure in the
specification of the question. Many of you assumed that the
linked list would be like dllists: circular with a sentinel node.
That is not what I specified.
Also, you cannot call malloc(), sbrk() or
dll_append() in free() -- you are supposed to
be putting memory back on the freelist, not allocating more
memory....
Here is the point allocation:
- Backing up and setting fn to the right memory location: 2 points.
- Checking the checksum: 1 point
- Checking it correctly: 1 more point
- Checking the size to see if it is a multiple of 8: 2 points
- Checking the size to see if it is less than 0: 1 point
- Checking the size to see if it is less than 16: 1 more point
- Decrementing the size: 1 point
- Hooking fn onto the freelist correctly: 4 points
- Dumping core correctly (dereferencing a NULL pointer is the
easiest way): 2 points
- You lost points for doing extraneous things incorrectly (like
setting the checksum to something incorrect).
I was liberal about your omitting type casts and messing up types.
Remember -- if you dereference a void * you get a void,
which is not equivalent to an int or a char.