The following is the slightly edited text of two messages Ken Bloom (a past TA) posted to help students working on the malloc lab:

General recommendations

I have several recommendations for techniques as you start your malloc labs.

My first recommendation is to modify the makefile so that CFLAGS includes -Werror. g++ will by default only emit warnings for pointer type conversion errors, but people who ignore these warnings will go completely insane trying to make their code work on something where pointers are as critical as they are in this lab. -Werror will turn these (and other warnings) into compiler errors so that you will have to fix them. (If you run "git pull" to update your lab from GitHub, which is working now, you will see that this has already been done for you.)

Last time I TA'ed this class, I noticed that students were consulting the textbook a lot and following its lead by using PUT() and GET() macros to access memory. This will lead to C code that is as difficult to understand as assembly language, becuase the code will mimic the use of load and store instructions in your assembly language. This too is a recipe for insanity. I suggest that you represent the header at the beginning of a free block by using a struct, for example

typedef struct header_t {
  size_t size;
  /* whatever other fields you want to include
  * to maintain a list of free blocks */
} header_t;

You should create functions to convert from these to userspace pointers that will be passed to and from mm_malloc, mm_free and mm_realloc.

header_t* fromuserptr(void* userptr);
void* touserptr(header_t* header);

Many sensible implementations of malloc store a copy of the size of a free block at the top of that block. Someone storing data at the to of a block should create a function like

size_t* topofblock(header_t *cur);

to access the top of the block. (If you put something else there, like a struct or a pointer, you should change the return type accordingly.)

When you need to deal with pairs of adjacent blocks (for example in mm_realloc, or to avoid fragmentation in mm_free and mm_malloc), you should create an API for dealing with this. In my code, I had

header_t* nextinram(header_t * cur);
header_t* previnram(header_t * cur);
void coalesce_blocks(header_t* cur, header_t* next);
void split_block(header_t* cur, size_t newsize);

Finally, you should create a set of functions for dealing with the freelist, and make sure all freelist management is done through those functions. You should implement a very simple free list, focus on getting the mm_* functions working, and then when you've done that you can create a more efficient and more complicated freelist implementation without breaking the rest of their code. (And thanks to the header_t struct that you created before, the stuff that goes in here should look a lot like what you'll find in any elementary data structures book.)

void freelist_add(header_t* cur);
void freelist_remove(header_t* cur);
header_t* freelist_find(size_t size);

You can consult this article about Doug Lea's malloc, which was at one point used in the GNU C Library. (I'm not sure whether it still is the algorithm that' used.) In there, you can find diagrams of the memory layout used by his allocator.

Structs and the malloc lab

A couple people have asked me about how I could create a

struct header_t

when the lab guidelines say

You are not allowed to define any global or static compound data structures such as arrays, structs, trees, or lists in your mm.c program. However, you are allowed to declare global scalar variables such as integers, floats, and pointers in mm.c.

To clarify, this requirement doesn't prevent you from creating typedefs of structs and other such things. What it does prevent you from doing is from mainitining your free list using lots of global variables. (For example declaring a global

void* freelist[1000]

or something like that.)

You are allowed to define structs, but if you're going to allocate them, they must live on your heap. This means that you allocate space in several ways, for example by calling

mem_sbrk

and typecasting the result to be a pointer to the

struct type, or typecasting the pointer that's passed to

mm_free

to be a pointer to the struct type.