Posted By: Charles | Jun 16th @ 10:28 AM

The Visual C++ runtime library now detects incorrect iterator use and will assert and display a dialog box at run time. To enable debug iterator support, a program must be compiled with a debug version of a C run time library (see C Run-Time Libraries for more information).

See Checked Iterators for more information on using iterators.

The C++ standard describes which member functions cause iterators to a container to become invalid. Two examples are:

  • Erasing an element from a container causes iterators to the element to become invalid.

  • Increasing the size of a vector (push or insert) causes iterators into the vector container become invalid.

Here, VC++ Software Engineer Stephan T. Lavavej digs into the details of STL Iterator Debugging including its implementation, usage scenarios and interesting facts you may not find anywhere else (Channel 9 goodness). Stephan is known as STL (this is his name's acronym, by coincidence or perhaps it's simply prophetic since Stephan is a passionate advocate for STL, as you will no doubt understand after watching and listening to this conversation). Stephan also dives a bit into Secure SCL, which is part of the VC++ Safe Libraries.

Stephan does not possess a marketing bone in his body as you can tell by his commentary that's weaved into his informal presentation of advanced topics. I love this. He speaks his mind freely, though with fairness, and that's the only way to be.

Enjoy!

Tags: , ,
Rating:
0
0
Thanks for doing this interview Charles. This is a topic that I'm very interested in...
Right on, Littleguru. This is indeed fascinating stuff. The C++ team is one of our best from an engineering perspective. The language remains very strong and is evolving to suit the needs of the future. STL in particular is a library that more C++ devs should use. Lots of powerful constructs just like Iterator Debugging. With the advent of Phoenix, you can expect some really interesting compilation tools (static analysis tools in particular) to pop up over time making C++ code safer, more robust and more performant...
I wonder why the iterator is not following to the new location, when the resizing of a vector happens. Is that to slow or why isn't that implemented?

And why is it a linked list that keeps track of the iterators and not a "vector"-like (dynamic array) construct?

For one thing, the C++ standard actually specifies that a vector reallocation invalidates all iterators and pointers. If VC would do otherwise, it would break the standard (this is probably because when the standard was written a lot of implementations were already around, and a lot of those used plain pointers for the vector iterators, as the video says).

Also, if this was implemented it would likely have a similar cost to what iterator debugging has. Only, now you can't turn it off for your release builds because it would change the semantics of your program. It would simply be too slow.

*Raises hand as one of those C++ developers that always disables secure scl.  Not only is perf affected, but depending on your usage it can bloat up the binary size quite a bit.

First things I do when creating a new project:

#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS

#ifndef _DEBUG
#define _SECURE_SCL 0
#endif

#define NOMINMAX

[littleguru]
> I wonder why the iterator is not following to the new location, when the resizing of a vector happens.
> Is that to slow or why isn't that implemented?

It would be way too expensive (both space and time). C++ is supposed to be blazingly fast, so the Standard avoids mandating anything that could be expensive. Especially when it doesn't buy anything fundamentally useful.

It would actually be more expensive than _SECURE_SCL, which is already unloved.

You can always use indices, which aren't invalidated by reallocation.

> And why is it a linked list that keeps track of the iterators and not a "vector"-like (dynamic array) construct?

_HAS_ITERATOR_DEBUGGING's singly-linked list is actually formed from the iterators themselves, which avoids performing any dynamic memory allocations. The iterators of Standard containers aren't allowed to have throwing copy ctors (23.1/10), which is exactly what dynamic memory allocations would do.

[Sven Groot]
> For one thing, the C++ standard actually specifies that a vector reallocation invalidates all iterators and pointers.

Note that the Standard's idea of invalidation is a theoretical concept. Iterators, pointers, and references can be theoretically invalidated (e.g. by vector reallocation) without being physically invalidated. For example, if we attempted and succeeded at in-place reallocation, then we wouldn't physically invalidate anything, but the Standard would still say that things have been theoretically invalidated.

> If VC would do otherwise, it would break the standard

If the Standard says that X theoretically invalidates Y, then it's conformant to make X not physically invalidate Y.

[PhrostByte]
> Raises hand as one of those C++ developers that always disables secure scl.

You have to be careful when doing this, as I mentioned in the video, if you use something like Boost.

Stephan T. Lavavej, Visual C++ Libraries Developer

I know it's conformant, but it would be dangerous. People would write code like that on VC, find it works, and then get in trouble when porting to other platforms.

We'll certainly avoid physical invalidation whenever there are performance advantages in doing so (e.g. in-place reallocation, which I'm looking at for VC10).

_HAS_ITERATOR_DEBUGGING will always complain about theoretical invalidation, and it is extremely strict.  For example, if you insert-at-middle without triggering reallocation, you've theoretically invalidated all iterators beyond the inserted element.  Erasing that element doesn't make those iterators theoretically valid again, but they'll be physically valid.