I am having a hard time understanding sbrk()
and mmap()
, as well as munmap()
.
This is closely related to How do I free memory obtained by sbrk()? but I have more questions.
If I have the following program:
int main(void) {
void* first = sbrk(4096);
void* second = sbrk(4096);
return 0;
}
From what I understand, sbrk()
will increase the size of the heap by the value that was passed in, and then return a pointer to the beginning of that memory segment.
So for example if the current heap break (end of heap) is at 0x1000, and I call void* first = sbrk(4096)
, the heap break will then be at 0x2000 and the pointer returned will be 0x1000.
So I assume then that when I call void* second = sbrk(4096)
, the heap break will be at 0x3000 and the pointer returned will be 0x2000?
When it comes to freeing this memory, I understand that if you call sbrk()
again, I think sbrk(-4096), that will free heap memory. But won't that free void* second
, what happens if I want to free void* first
?
Also, can I used munmap to unmap that allocated memory from sbrk()
? So call something like munmap(second, 4096);
or can that only be used if I used mmap()
to allocate the memory?
Thanks, Juan
Please note, this is for a university assignment, I would just use malloc and free but the assignment is to reimplement malloc.
So I assume then that when I call void* second = sbrk(4096), the heap break will be at 0x3000 and the pointer returned will be 0x2000?
Yes.
When it comes to freeing this memory, I understand that if you call sbrk() again, I think sbrk(-4096), that will free heap memory. But won't that free void* second,
It will "free second" - free 4096 bytes.
what happens if I want to free void* first?
You have to call them in order.
void *first = sbrk(4096);
void *second = sbrk(4096);
sbrk(-4096);
sbrk(-4096);
or just sbrk(-4096 * 2);
.
can I used munmap to unmap that allocated memory from sbrk()?
No.
So call something like munmap(second, 4096);
No.
or can that only be used if I used mmap() to allocate the memory?
Yes.
Sbrk moves a pointer and returns an older address. A over-simplistic implementation could be like:
char heap_memory[1000000];
char *heap = heap_memory;
char *heap_end = heap + 1000000;
void *sbrk(int toadd) {
// check for out of memory
if (heap + toadd > heap_end) return NULL;
// increment heap and return the old address
char *old_address = heap;
heap += toadd;
return old_address;
}
Just moves a pointer within some buffer. mmap
is a different mechanisms, that maps the memory address you chose to some data. You can't pass value returned by sbrk
to mmap
.