On 2007-1-29 10:15 UTC, Chris Trobridge wrote:
> Greg Chicares wrote:
>> Wouldn't 'vec[vec.size()]' be undefined behavior and a likely
>> reason for the program to crash?
> I have only "C++ in a nutshell" to act as a reference.
> It states that the elements of the vector are stored contiguously in
> memory, like an array, so at one level I don't think this is undefined
> behaviour, assuming the book I have is correct.
Valid subscripts run from 0 through size()-1 inclusive.
'vec[vec.size()]' attempts to return a reference to something
outside the valid range, and that has undefined behavior.
> I'd have thought that vec.end() would be more appropriate, but this is,
> in effect, defined as &vec[vec.size()] anyway...
'vec.end()' and '&vec[vec.size()]' are not equivalent.
'vec.end()' is all right. It yields a one-past-the-end
iterator. You can obtain such an iterator, and you can
compare it to another iterator, but you mustn't dereference
it. '&vec[vec.size()]' attempts to perform a dereference
before it applies '&'. That's the difference.
> So I would say end() is better as it avoids impression of accessing an
> element outside of the vector.
That's not just an impression: 'vec[vec.size()]' really
does attempt to dereference something past the end, and its
behavior is undefined.
> The debug 'crash' is not entirely appropriate as there is no attempt to
> access an element, merely to obtain the address past the end of the
> vector, which is required for other stl operations. As I said, this is
> exactly what end() does but more clearly and explicitly stated.
It's undefined behavior, so it can crash.
'&X[Y]' is not equivalent to 'X+Y'. The former means
'&(*(X+Y))'. The compiler doesn't look at the '*' and '&'
and cancel them against each other; instead, it attempts
to perform them in sequence. (The C language was changed
in 1999, so that the '&' and '*' do cancel; even if that
rule is eventually embraced by C++, it'll apply only to
arrays, not STL containers, because containers can
> Finally while complains about the above, the debugger doesn't complain
> about (&vec+vec.size()], which is also equivalent.
Again, what matters is whether it's dereferenced.
> I think he should have used end() in the first place...
> The big puzzle is why the program ultimately ends the way it should?
Because it's undefined behavior. UB is an important defined
term, not a loose concept. One possible consequence of UB
is a crash.
> Surely an exception has been thrrown by the debug code but the
> runtime/environment is catching this? Is there a particular compiler
> setting to get exceptions reported properly?
A segmentation violation is not a C++ exception. There's
no compiler setting to trap segmentation violations. The
compiler is performing properly.
If you want bounds-checked access to a std::vector, with a
C++ exception thrown if the bounds are violated, use at().