Search code examples
c++11gccstdlist

Dereference list::end()


I was playing around with std::list. Similarly to other containers, std::list::end refers to the past-the-end element of a std::list (ref).

So, we would expect the below code to print 1, 2, 3, 4, 5 (which it does):

std::list<int> l { 1, 2, 3, 4, 5 };
for (auto it = l.begin(); it != l.end(); ++it)
{
    std::cout << *it << ", ";
}
std::cout << std::endl;

However, the second line of the second code snippet should not print 5, but it does:

std::cout << *l.begin() << std::endl;
std::cout << *l.end() << std::endl;

Output: 1 and 5.

Why? I'm using GCC 11 and C++11 (same for C++20 btw).


Solution

  • You can see the reason if you build in debug mode, with the -D_GLIBCXX_DEBUG command line flag:

    /usr/include/c++/8/debug/safe_iterator.h:270:
    Error: attempt to dereference a past-the-end iterator.
    
    Objects involved in the operation:
        iterator "this" @ 0x0x7fff50ac8670 {
          type = __gnu_debug::_Safe_iterator<std::__cxx1998::_List_iterator<int>, std::__debug::list<int, std::allocator<int> > > (mutable iterator);
          state = past-the-end;
          references sequence with type 'std::__debug::list<int, std::allocator<int> >' @ 0x0x7fff50ac85d0
        }
    Aborted
    

    As with other containers, dereferencing the end() iterator is undefined. It only happens to work by accident in non-debug mode.