Why does calling sbrk(0) twice give a different value?
Asked Answered
B

1

18

I'm trying to understand the sbrk() function.

From what I know:
sbrk(0) returns the current address of the break and doesn't increment it.
sbrk(size) increments the address of the break by size bytes and returns the previous address of the break.

So I created something to test it:

#include <unistd.h>
#include <stdio.h>

int main(void)
{
    printf("sbrk(0) = %p\n", sbrk(0)); // should return value x
    printf("sbrk(0) = %p\n", sbrk(0)); // should return value x
    printf("sbrk(5) = %p\n", sbrk(5)); // should return value x
    printf("sbrk(0) = %p\n", sbrk(0)); // should return value x + 5
}

So I'm expecting to see a result looking like this:

sbrk(0) = 0x1677000 // x value
sbrk(0) = 0x1677000 // x value
sbrk(5) = 0x1677000 // x value
sbrk(0) = 0x1677005 // x value + 5

but instead I'm getting this:

sbrk(0) = 0x1677000 // x value
sbrk(0) = 0x1698000 // y value
sbrk(5) = 0x1698000 // y value
sbrk(0) = 0x1698005 // y value + 5

Why don't the first two calls of sbrk(0) return the same value? What happens between those two calls that changes the break address?

EDIT : Storing addresses in variables solves the problem:

int main(void)
{
    void *toto1 = sbrk(0);
    void *toto2 = sbrk(0);
    void *toto3 = sbrk(5);
    void *toto4 = sbrk(0);

    printf("sbrk(0) = %p\n", toto1);
    printf("sbrk(0) = %p\n", toto2);
    printf("sbrk(5) = %p\n", toto3);
    printf("sbrk(0) = %p\n", toto4);
}

Bekah answered 21/1, 2019 at 17:7 Comment(10)
printf might use some dynamic memory stuff. Try assigning the values to variables instead and print them at once.Unusual
I tried it just now, it doesn't change anything, the printf doesn't have an influence on that apparently.Bekah
Then please update your question with the other code as well, so no one will repeat this assumption.Unusual
You need to use multiple variables, and do all calls to sbrk before calling printf. Your updated code does basically just the same as the first and will have the same problem.Reeves
Maybe use this checklist:codeblog.jonskeet.uk/2012/11/24/…Meimeibers
The updated code does not eliminate the possibility I was talking about. You are still interleaving it with printfsUnusual
Yes, that's my bad sorry, I tried it with variables for each call and it solves the problem. So it was basically because of the memory management done by printf ? And if so, why did it occurs only on the first 2 calls ?Bekah
You will probably need to look at your specific printf implementation to find out.Unusual
My guess is that the initialization of the standard I/O parts is done lazily. That is, the initialization is done when they are needed, and part of that initialization is allocation of the buffer for stdout.Reeves
Here is the argument handling code of glibc: github.com/bminor/glibc/blob/master/stdio-common/… It calls malloc() in a few places.Percaline
G
15

Your program performs the following sequence of calls:

sbrk()
printf()
sbrk()
printf()
...

The first call to printf calls malloc internally to allocate a buffer for stdout (stdout is line buffered by default, but the buffer is created on demand the first time you print to it).

That's why the second call to sbrk returns a different value.

(This answer is not directly related, but the error messages from valgrind expose the existence of the underlying malloc call hidden inside printf.)

Your second example performs all sbrk calls up front, so there are no surprises from other functions calling malloc behind your back.

Gala answered 21/1, 2019 at 19:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.