Posted By: Charles | Jun 16th, 2008 @ 10:28 AM | 28,948 Views | 9 Comments

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: C++, Secure SCL, STL
Rating:
0
0
littleguru
littleguru
summer time! aperol spritz dreaming...
Thanks for doing this interview Charles. This is a topic that I'm very interested in...
littleguru
littleguru
summer time! aperol spritz dreaming...
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?
Sven Groot
Sven Groot
Gravity is a CIA plot to keep us on Earth.

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
STL
STL

[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

Sven Groot
Sven Groot
Gravity is a CIA plot to keep us on Earth.
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.
STL
STL

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.

Hi,

I love _HAS_ITERATOR_DEBUGGING. I am relieved to hear that it complains about theoretical validation too, it should. That is what debug builds are for. My experience is that for 99% the slowdown due to the STL checking is irrelevant.

Having said that, I have a few files where we would welcome the opportunity to disable it. That is because our software has some image processing, that only one or two people are interested in debugging anyway, and usually only when they're working on bugs in that portion of the code. Now, I am expecting that undefining _HAS_ITERATOR_DEBUGGING for one file will lead to ODR violations, for sure if it shares containers with other classes in the dll. I can use plain pointers, but is there no other way?
Microsoft Communities