Shivanshu Arora
Shivanshu Arora

Reputation: 135

Does sbrk(0) also allocate memory behind the scenes? No segfault when I store above 2K the break

I am learning how sbrk, brk, mmap etc work and what they offer. I am writing a very basic code like this

int main(int argc, char* argv[]) {
void* f1 = sbrk(0);
  int* newarr = (int*)f1;
  for(int i=0;i<2048;i++) {
    newarr[i] = 1;
  }
  cout<<newarr[9]<<endl;
return 0;
}

In this case, I have simply done sbrk(0), to find out the current program break, however, as you can see, I am also able to create a newarr of length 2048 or even more and use it. This means I have the memory on the heap now without actually moving the program break. Note that I have not done any other brk or sbrk calls, other than doing sbrk(0), so my guess is that heap is empty right now?

How is it working? My understanding was that I have to move the program break by some bytes and I can only use those bytes, otherwise it would be a segfault.

Edit: I found this link https://iq.opengenus.org/mmap-brk-and-sbrk-in-unix/ which says that a default space of 100k is allocated the first time sbrk is called, so that must be the reason for this behavior? But if I do sbrk(0) multiple times and print program break, its all the same

Upvotes: 2

Views: 86

Answers (1)

user22405329
user22405329

Reputation: 969

The OS can only allocate memory in pages. On x86, for example, the page size is 4kiB (4096 bytes), so the kernel can either allocate 4096 bytes or not. Also, your program's data segment is very unlikely to stop exactly at 4k boundary - so the leftover space will just be there, even if it is technically after the program break. The MMU protection works on whole pages only, so the kernel has no way to enforce the break barrier.

The article's claim doesn't seem to be correct. I've looked at the GLIBC source for sbrk, and also the source for brk - and I see no mention of _mneed variable or 100k default. The code in the kernel just does a page alignment, and calls mmap.

Upvotes: 3

Related Questions