In this section, we'll write a program that deliberately accesses an invalidated iterator:
- First, we include headers.
#include <iostream>
#include <vector>
- Now, let's instantiate a vector of integers and get an iterator to the first item, the value 1. We apply shrink_to_fit() on the vector in order to ensure that its capacity is really 3, as its implementation might allocate more memory than necessary as a little reserve to make future item insertions faster:
int main()
{
std::vector<int> v {1, 2, 3};
v.shrink_to_fit();
const auto it (std::begin(v));
- Then we print the dereferenced iterator, which is completely fine:
std::cout << *it << 'n';
- Next, let's append a new number to the vector. As the vector is not large enough to take another number, it will automatically increase its size. It does this by allocating a new and larger chunk of memory, moving all the existing items to that new chunk and then deleting the old memory chunk:
v.push_back(123);
- Now, let's print 1 from the vector through this iterator again. This is bad. Why? Well, when the vector moved all its values to the new chunk of memory and threw away the old chunk, it did not tell the iterator about this change. This means that the iterator is still pointing to the old location, and we cannot know what really happened to it since then:
std::cout << *it << 'n'; // bad bad bad!
}
- Compiling and running this program leads to a flawless execution. The app doesn't crash, but what it prints when dereferencing the invalidated pointer is pretty much random. Leaving it like this is pretty dangerous, but at this point, no one tells us about that bug if we don't see it ourselves:

- Debug flags come to the rescue! The GNU STL implementation supports a preprocessor macro called _GLIBCXX_DEBUG, which activates a lot of sanity checking code in the STL. This makes the program slower, but it finds bugs. We can activate it by adding a -D_GLIBCXX_DEBUG flag to our compiler command line, or define it in the head of the code file before the include lines. As you can see, it kills the app in the mactivate different sanitizers. Let's compile the code with clan useful (the activation flag for checked iterators with the Microsoft Visual C++ compiler is /D_ITERATOR_DEBUG_LEVEL=1):

- The LLVM/clang implementation of the STL also has debug flags, but they serve the purpose of debugging the STL itself, not user code. For user code, you can activate different sanitizers. Let's compile the code with clang using the -fsanitize=address -fsanitize=undefined flags and see what happens:

Wow, this is a very precise description of what went wrong. The screenshot would have spanned multiple pages of this book if it had not been truncated. Note that this is not a clang-only feature, as it also works with GCC.
If you get runtime errors because some library is missing, then your compiler did not automatically ship with libasan and libubsan. Try to install them via your package manager or something similar.