1

Tried following code on 32 bit ubuntu virtual machine:

static int a[0x1f0fff];
cout << &a[0x600000] << endl;
cout << &a[0x800000] << endl;
cout << &a[0x8fff00000] << endl;

0x984a140
0xa04a140
0x7c4a140

Really confused that the address do not keep increasing.

The array located in heap, and what printed is virtual memory address. Is it because that it exceeds virtual memory space?

Besides, according to another answer, the last two line codes are indexing into a part of memory that is not allocated. Why is there no segfault reported?

Community
  • 1
  • 1
heLomaN
  • 1,634
  • 2
  • 22
  • 33

3 Answers3

3

Your hexadecimal notation, whilst flashy, is no more than an obfuscation (although the type inference rules for hexadecimal literals differ from denary literals).

The behaviour of your code is undefined but perhaps not for the reason that you might think.

Note that &a[0x600000] doesn't actually attempt to dereference the non-existent (0x600000)th element of a before taking the address of it. The compiler is required to evaluate the expression as a + 0x600000. But:

Setting a pointer to an address that is not an element within your array a, or one past the end of that array is undefined behaviour. As such the compiler is allowed to output anything.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Thank you. I got the logic. Undefined behavior is unreasonable. But have seen following code used many times:`#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)`. Is this ok to use address 0? – heLomaN Oct 18 '16 at 11:59
  • 1
    @heLomaN: It's certainly OK in C (and idiomatic in C), I can't recall for C++. Perhaps ask it as a question. – Bathsheba Oct 18 '16 at 12:09
  • @heLomaN: `offsetof` is part of your implementation, and must be because you can't write it yourself. As part of your implementation, your _particular_ implementation may use `(TYPE*)0` in this way. Another common implementation is `#define offsetof __builtin_offsetof` – MSalters Oct 19 '16 at 08:06
2

Undefined behaviour is not segfault. You hope for segfault. Sometimes you get nasal demons.

Why this particular behaviour? 32 bit unsigned math mod 2^32. Not guaranteed to happen, but I am pretty certain that is what the compiled result is doing here.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • Thank you. I shouldn't try undefined code. But the math is not right, 0xa04a140 + 0x8fff00000 - 0x800000 != 0x7c4a140. Might because undefined. – heLomaN Oct 18 '16 at 12:05
  • @helo mod 2^32 with a `*sizeof(int)` it does equal. Pointer arithmetic has each `+1` adding `+sizeof(int)` here. – Yakk - Adam Nevraumont Oct 18 '16 at 12:08
1

Besides, according to another answer, the last two line codes are indexing into a part of memory that is not allocated. Why is there no segfault reported?

Accessing array out-of-bound is undefined behaviour, that means anything can happen, and that also means there is NO guarantee of a segfault - it may happen one time, it may not happen the next time (that's why it's called undefined).

artm
  • 17,291
  • 6
  • 38
  • 54