Reputation: 189
I've been writing an implementation of malloc and was wondering if someone could help me with this problem.
Basically, I would like to reuse memory after allocating it using sbrk(), and having made certain that the memory is free.
So essentially, imagine my memory is like this
|------------------------------|
...and I do some allocations. When I allocate memory, each bit has a head (h) and data (d).
|hddddddhddd---hdd--hddd-------|
Now I've got these holes, and if I want to use say, the first gap in my diagram, how do I set it up so that it's got a head (h) and a body (dd) also?
I've gotten to the point where now I've got a pointer to the memory location I want. In C, its pointed to by a pointer. The pointer has a custom type, where "meta" is a struct I defined. So now I have
metaStruct * mypointer = the memory address.
But when I try to do
mypointer->size = 30;
Or
mypointer->buddy = 1;
I get a segfault.
The question: how do I set it up so that the memory address, which has been allocated via sbrk(), will have the form of my struct? Obviously I can't just go myPointer = malloc(sizeof(metaStruct)), because I am writing malloc itself. I'm also not interested in sbrk()'ing more space, but rather, utilizing the existing space that I'm pointing to (I want to disregard its junk data and use the space).
How do I go about doing that?
Upvotes: 4
Views: 5337
Reputation: 4426
As far as I know, p=sbrk(n) enlarges the available address space of (at least) n bytes and returns the base address of the new allocated area in "p". So you now have a block of memory starting at "p" and n bytes long (probably more than n, it depends on the system).
So I suppose that your "metaStruct" contains a "size" field, a "next free area" field, and a "data" field,
metaStruct * m ;
p=sbrk(sizeof(metaStruct)+ data_size);
m = (metaStruct *)p;
m->size = data_size;
m->next = NULL;
memcpy(m->data, ...,data_size);
The code is not perfect, on some systems the sbrk function (indeed it's often a function, not a basic system call - and of course you should check if sbrk fails) doesn't return aligned pointers, so you have to align the pointer manually. Also, you can obtain the actual allocated size by calling sbrk(0) after sbrk(n) and calculating the difference between the two pointers. In general, you should mainatin a collection of "free blocks" and try to use them fist, then call sbrk only if none of them is large enough.
Upvotes: 4