7

I was looking at the documentation of sbrk system call and found this:

On success, sbrk() returns the previous program break. (If the break was increased, then this value is a pointer to the start of the newly allocated memory). On error, (void *) -1 is returned, and errno is set to ENOMEM.

Now,

  1. What's the significance of (void *) -1?

  2. What is the exact memory address it points to? (if it does at all)

  3. How is it guaranteed that (void *) -1 is not a valid address that can be returned by sbrk() on success?

Ohad Eytan
  • 8,114
  • 1
  • 22
  • 31
tomol
  • 755
  • 1
  • 6
  • 12

2 Answers2

8
(void *) -1 == (size_t) -1

It's 0xFFFFFFFF on 32 bit machine and 0xFFFFFFFFFFFFFFFF on 64 bit machine, an invalid address that is supposed to be bigger than any other address.

taskinoor
  • 45,586
  • 12
  • 116
  • 142
MichaelMoser
  • 3,172
  • 1
  • 26
  • 26
  • I'm sorry if I sound totally noob, but how is `(void *) -1` equal to `0xFFFFFFFF` – tomol Jul 24 '16 at 09:14
  • 3
    @tomol, read up on [2s complement](https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html) – Matt Jul 24 '16 at 09:15
  • 3
    @tomol , think of it in the other direction, how much is `0xFFFFFFFF + 1`? it's `0`!... Once the variable experiences overflow due to it's bitsize limits, interesting things can happen ;-) – Myst Jul 24 '16 at 09:19
  • @Matt you're wrong. C standard doesn't say anything about 2s complement. – tomol Jul 24 '16 at 09:23
  • @tomol, and yet a compiled `c` program doesn't run in a vacuum. Something like the Llinux kernel which is architecture aware, can safely say that `0xFFFFFFFF` is `-1` – StoryTeller - Unslander Monica Jul 24 '16 at 09:28
  • @tomol The C standard doesn't say anything about `sbrk` either. This whole thing is inherently implementation specific. – melpomene Jul 24 '16 at 09:30
  • I would challenge the term "invalid" - It is a perfectly valid address addressing the highest addressable byte in the address space. It is, however, a non-sensible address to be returned by `sbrk()` and thus can be used to signal failure. – tofro Jul 24 '16 at 09:41
2
  1. What's the significance of (void *) -1?

It's simply a sentinel value that sbrk() would be incapable of returning in a successful case.

  1. What is the exact memory address it points to? (if it does at all)

It's not expected to be a valid address, and the specific value is not relevant.

  1. How is it guaranteed that (void *) -1 is not a valid address that can be returned by sbrk() on success?

It perhaps seems like circular reasoning, but it's guaranteed because sbrk() guarantees it as part of its contract. (For example, sbrk() could check whether it would return that value if successful; if so, it instead could do nothing and report failure.)

In practice, (void*) -1 on most modern machines is going to be 0xFF...FF, which would be the highest possible address, and that's simply something that's unlikely to be valid.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • 1
    Furthermore even if `0xFF..FF` was a valid address, as far as systems that have the `sbrk` syscall are concerned this is an address in kernel space, which is not reachable while in user mode. Technically `sbrk` could return *any* address in kernel space to user mode code to indicate an error. – datenwolf Jul 24 '16 at 09:42