What does sbrk(0) point to when initializing static variables?

Viewed 174

In the sbrk(2) manual,

it states that

Calling sbrk() with an increment of 0 can be used to find the current location of the program break.

How does this work when sbrk(0) is used to initialize a static variable?

Say,

static void* current_heap = sbrk(0);

This curiosity stems from the typical compilation steps of C/C++ code determine the size of the data segment at compile time.

As shown in the diagram below,

Memory layout

Distributed under CC BY-SA 3.0

the initialized static variables are stored in the data segment. And as far as I know, the heap normally starts from the end of BSS and data segments.

How does sbrk(0) know where heap starts during compilation while other static variables might not have been determined?

UPDATE:

As noted by @EugeneSh, here's a working example compiled with clang++:

#include <unistd.h>
#include <iostream>

static void* current_heap = sbrk(0);

int main() {
  std::cout << current_heap << '\n';
}
2 Answers

In C, this code is not valid:

static void* current_heap = sbrk(0);

Because an initializer for an object with static storage duration must be a compile time constant, which this is not. So this code will fail to compile in C.

For C++, the function will be called when the program runs at some point before main is called.

So there is no compile-time call to sbrk.

As for what section this variable would reside in, it would most likely be in .bss because it is not initialized at compile time. Indeed, if I compile your code with g++ the variable is placed in .bss.

Per the C standard, 6.7.9:

All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.

This is therefore not a valid initialization in C.

In C++ it would be a run-time initialization.

Related