https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91357
Bug ID: 91357 Summary: _GLIBCXX_ASSERTIONS rejects possibly-valid code Product: gcc Version: 9.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: luto at kernel dot org Target Milestone: --- Created attachment 46672 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46672&action=edit Example For a non-empty vector v, calling v.operator[](v.size()) fires this assertion: /usr/include/c++/9/bits/stl_vector.h:1042: std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[](std::vector<_Tp, _Alloc>::size_type) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::reference = int&; std::vector<_Tp, _Alloc>::size_type = long unsigned int]: Assertion '__builtin_expect(__n < this->size(), true)' failed. After some digging into the standard, I'm not entirely sure whether that particular invocation of operator[] is UB or otherwise invalid. It's certainly poor form -- the right way in modern C++ to form a one-past-the-end pointer to a vector is (v.data() + v.size()), but, if it's indeed legal, then _GLIBCXX_ASSERTIONS should not be firing. I suggest one of the following resolutions: 1. Determine that merely calling v.operator[](v.size()) is UB or that it is otherwise permissible for a conforming implementation to crash when this happens. This would require some careful standard reading and maybe even a change to the standard. 2. Weaken the assertion to only crash if the index is strictly greater than the size. Calling v.operator[](v.size() + 1) is definitely UB (except perhaps in the pathological case where v.size() + 1 == 0, but I doubt it's possible to make a vector that large on any supported platform). 3. Use compiler magic to only fire the assertion if the pointer returned by operator[] is dereferenced for real, e.g. dereferenced and converted to an lvalue. Maybe gcc could gain a builtin like __builtin_return_value_is_definitely_dereferenced(). 4. Improve the assertion so that, when this assertion fires, a very clear message is printed to stderr saying something like "This assertion fired due to the formation of a one-past-the-end reference. This may indicate a stylistic issue with the program but is not necessarily a bug."