1

The Linux Man Page for sbrk() states that upon failure, it returns (void*) -1. What is (void*) -1 and does it have any significance or is it simply a number that could never actually be a void* which is cast to a void* just to meet the function signature of returning a void*? I ask this because I've never seen a pointer to a negative address before. I did not know this was possible to dereference on any platform.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
the_endian
  • 2,259
  • 1
  • 24
  • 49

2 Answers2

2

It is just, as you guessed, a way to return the magic value -1. It is being cast to a pointer just to match the function signature. The caller will know how to interpret this magic value and not attempt to dereference it.

Internally, this would actually just become 0xFFFFFFFFFFFFFFFF (or 0xFFFFFFFF for 32 bit). There may be platforms where this address can actually be accessed, but that is not the purpose here.

CherryDT
  • 25,571
  • 5
  • 49
  • 74
2

In most operating systems, memory is allocated in a set of pages (these can be in physical RAM or they can be virtual pages that are stored on a permanent storage disk/device and are usually 4KB each). Since -1 (unsigned 0xFFFFFFFFFFFFFFFF or 0xFFFFFFFF for 32 bit) is the largest possible value for a QWORD (or DWORD for 32 bit) a page usually cannot start at this address because it is the very last address in the address space. Therefore -1 is a good value to use to indicate an error in memory allocation because it is usually considered a non-existent page. As for a pointer to a negative address, your compiler is responsible for enforcing sign in its code generation if you ever have had experience with assembly you will recall that a variable doesn't implicitly have sign (only the instructions give it this property). When you access a region of memory in assembly the address is considered to be an unsigned number.

  • The reasoning that pages usually cannot start at “−1” because it is the largest address is specious. Operating systems and programs are not required to allocate memory in sequential order. Humans design schemes to organize memory. For example, we might split memory into a portion for user program use and a portion for system use. Within those, we might start at the “bottom” (low-numbered addresses) and say that space will be used for data, then set aside other space at the “top” for stack, carve out some space in the middle for various purposes, and so on. So the “top” might well be mapped. – Eric Postpischil Mar 08 '20 at 12:53
  • The top can be mapped but it wouldnt be very sensible to have a memory page that starts at 0xFFFFFFFF because theres no more space after this. Granted you could use segment offset memory styles and setup a virtual address scheme to have a page start at 0xFFFFFFFF but the general notion for why this value is used in sbrk might actually be linux specific! Im not sure how the linux kernel sets up its memory (windows tends to spread out while i believe linux is less fragmented). – Andrew Strickland Mar 08 '20 at 15:35