3

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
Juan Pablo
  • 338
  • 2
  • 17
  • Hi @HansPassant, yes it is closely related to this one, I've got that question linked in this question, I just had further questions about it. – Juan Pablo Aug 19 '20 at 08:49

1 Answers1

3

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.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Yeah ok that makes sense. So when malloc is called in a C program, does it actually use sbrk()? I always thought that when allocating memory dynamically with malloc, you are given back a chunk of memory in a random location on the heap. Sounds like if it uses sbrk() it will just give back memory at the end of the heap, after it has allocated more memory.. just cant see how it would then free that? – Juan Pablo Aug 19 '20 at 08:48
  • 1
    `So when malloc is called in a C program, does it actually use sbrk()?` It _depends_. Depends on who has wrote the malloc. Some do, some don't, some do sometimes. In `glibc` malloc uses sbrt if the allocation is small, but uses mmap if allocation is big. In `newlib` malloc just uses sbrk - there is mmap on systems newlib is usually run on. `in a random location on the heap.` Think of as `sbrk` as a backend for `malloc`. Malloc has it's own internal list of chunks allocated within the memory returned from `sbrk` . Inside the memory in `sbrk` malloc creates a linked list of chunks, manages.. – KamilCuk Aug 19 '20 at 09:42
  • .. that memory and if it determines that it is full, then it calls sbrk. `malloc` calls `sbrk` with negative argument usually when it determines that the free trailing memory is greater then some value (see `mallopt` or `malloc_get_info` or similar in glibc). So `sbrk` is a simple "give me more memory" function. But what you do with that memory, is a lot more complicated within malloc. – KamilCuk Aug 19 '20 at 09:45