Suppose you are working with a partner to write malloc()
and free(). Your partner is writing malloc() and
you are writing free(). You have decided upon the following
implementation:
There will be one free list referenced by the global variable
Freelist. The type definition for free list nodes is:
typedef struct fnode {
int checksum;
int size;
struct fnode *flink;
struct fnode *blink;
} FNode;
Freelist is declared as follows:
FNode *Freelist = NULL;
and free() is defined as follows:
void free(void *ptr);
The free list will be NULL when empty. It is a doubly
linked list, terminated by NULL on both ends.
Each node in the free list includes a check-sum, which is
equal to the pointer value of the memory location of node itself, plus one.
The size field is equal to the size of the free list node.
We assume that pointers and integers are both 4 bytes.
Each time a user calls malloc(), the returned
chunk of memory will include 8 bytes of bookkeeping, all
allocated before the pointer that malloc() returns. The
first 4 bytes will be a checksum, defined to be one plus the
memory location of the checksum, and the next 4 bytes will be the
size of the entire chunk (bookkeeping plus memory returned to the
user), plus one.
Free() will return the chunk of memory pointed to by
ptr to the free list.
It will not coalesce chunks on the free list. It will check to make
sure that the checksum of the memory chunk is correct, and if not,
it will print an error message to standard error and dump core.
It should also check to make sure that the size of the chunk
is a reasonable value (don't worry about it being too large, but
you can check for other things), and if not,
print an error message to standard error
and dump core.