1

Consider a code like this:

std::vector<int> vec { 1, 2, 3 };
auto addr = &*vec.end();

or simplified:

int* ptr = 0;
auto addr = &*ptr;

It's obvious that auto val = *ptr; would segfault. Hence &*ptr is not accessing memory in the same way. Why is that the case? Is there a specific entry in standard for that?

  • 1
    "It's obvious that `auto val = *ptr;` would segfault." - it is? You would *hope* it would segfault, as that would make it far easier to discover your code has a defect, but alas invocation of *undefined behavior* (which happened the moment you applied the dereference operator to the container end-iterator) has no guarantees it will segfault, have all the appearance of "working", or anything else. The behavior is *undefined*; you can't rule *anything* out except definition of behavior. – WhozCraig Dec 01 '16 at 06:14

2 Answers2

5

Dereferencing the return value of std::vector::end() is cause for undefined behavior. There is no point trying to make sense of what happens if you do.

From http://en.cppreference.com/w/cpp/container/vector/end:

This element acts as a placeholder; attempting to access it results in undefined behavior.

Re. the second part, the only thing I could find in the C++11 standard is:

5.3.1 Unary operators

1 The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. If the type of the expression is “pointer to T,” the type of the result is “T.” [ Note: a pointer to an incomplete type (other than cv void) can be dereferenced. The lvalue thus obtained can be used in limited ways (to initialize a reference, for example); this lvalue must not be converted to a prvalue, see 4.1. — end note ]

The result of dereferencing a NULL pointer seems to be unspecified.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    that is not the question. See the 2nd example and explain why there is no seg fault – Rohith R Dec 01 '16 at 06:06
  • @PRP, the first of the question is just that. – R Sahu Dec 01 '16 at 06:09
  • 1
    The intended question is, while doing `auto addr = &(*ptr);` , isn't the pointer dereferenced first and then the address calculated. If yes, then why does the dereferencing of the pointer not give a seg fault. – Rohith R Dec 01 '16 at 06:12
  • @PRP, according to the OP, that's the simplified version of the first part of the question. – R Sahu Dec 01 '16 at 06:14
  • 1
    @PRP because the result of dereferencing a bad pointer is undefined. It could segfault. It could email an ascii art Mona Lisa to Cobra Commander. You don't know what it will do. – user4581301 Dec 01 '16 at 06:17
  • 1
    There are two related questions on SO: * http://stackoverflow.com/questions/2728299/why-is-comparing-against-end-iterator-legal * http://stackoverflow.com/questions/2728299/why-is-comparing-against-end-iterator-legal Note Stepanov's code in one and C standard quote in another. – Vladislavs Burakovs Dec 01 '16 at 06:21
3

In both cases you end up computing addresses rather than accessing memory, that is why your code happens to work. But both cases are undefined behavior according to c++ standard. The first example may actually trigger an assertion failure in Debug version of standard library.

Eugene
  • 6,194
  • 1
  • 20
  • 31
  • That's the question: if that's the case, where in standard is this distinction (accessing memory vs "computing address") made? – Vladislavs Burakovs Dec 01 '16 at 06:20
  • 1
    There is no distinction in the standard, both are undefined behavior. But in practice there is segfault only when the program needs to read contents of the memory. – Eugene Dec 01 '16 at 06:24