Introduction
Checked iterators are something I have known about for a while but never really bothered to use or understand better, until Microsoft Visual C++ 2005 was released. It came with a checked version of the Standard Library even in release mode and when porting the code from other compilers, I saw in practice both good and bad sides of using checked iterators. After working with checked iterators for a year and doing some research on the topic, I feel it is a good time to share the knowledge I gathered with the Code Project community. The article is structured as a series of questions and answers in an attempt to be short and an easy read.
Questions and Answers
What are checked iterators?
Checked iterators offer checked access to containers and other ranges. They are typically aware of the owning container and are able to catch some run-time errors that often lead to undefined behavior and then do something that is well-defined, like throwing an exception or terminating the application. This is particularly useful in avoiding security-related problems such as stack and heap overflows.
What kind of errors do checked iterators detect?
That really depends on their implementation. Some of the common errors they can catch are:
Uninitialized iterators:
vector<int>::iterator it;
it++;
Out of range access:
vector<int>::iterator it = vec.end();
it++;
Comparing iterators from different ranges or containers:
for (it = vec1.begin(); it != vec2.end(); ++it)
Can checked iterators detect other types of errors, such as invalid data in containers/ranges?
Yes. For instance, the UTF-8 CPP library version 2.0 or later has checked iterator adapters that are able to detect invalid utf-8 sequences:
utf8::iterator<std::string::iterator> it(u8string.begin(),
u8string.begin(), u8string.end());
it++;
Note that we passed the valid range boundaries as parameters to the constructor of the iterator adapter.
Are there checked containers as well, and if yes what are they good for?
Just as checked iterators keep track of their containers, containers can keep track of the iterators. That enables catching errors such as use of invalidated or "dangling" iterators:
vector<int> it = vec.begin();
vec.clear();
it++;
Is there an easy way to turn an unchecked iterator into a checked one?
Depends. Some STL implementations, like Dinkumware and STLPort offer both checked and unchecked versions, and switching between them is a simple matter of setting specific macros to a desired value. This is particularly handy if you want to use checked iterators in the debug mode and unchecked ones in the release mode, which is a pretty common scenario.
Other than that, you can write a checked iterator adapter that would turn an unchecked iterator into a checked one. In his classic book The C++ Programming Language, Bjarne Stroustrup gives an example of such an iterator adapter. In general, it could be declared something like:
template <typename base_iterator, typename container_type>
class checked_iterator;
and used like:
checked_iterator<myvectype::iterator, myvectype> it (vecit, vec);
it++;
Of course, such adapters are a poor man's replacement for a full-fledged checked STL implementation, but still may be very helpful.
Are there downsides to using checked iterators?
Yes - performance. Checked iterators are fatter and slower than their unchecked counterparts, and the difference in speed (rarely in memory footprint) can be significant. Sometimes it is a good idea to use checked iterators only during development and the first round of testing, and ship the software with unchecked iterators, but that really depends on a concrete situation.
Does Microsoft Visual C++ come with checked iterators?
Yes. In version 8.0 (VC++ 2005) the iterators and containers are checked by default even in release builds. To turn the checked iterators off, the _SECURE_SCL
macro must be set to 0. By default, in case an error is detected, the program gets terminated by calling invalid_parameter
. This behavior may be changed by setting the _SECURE_SCL_THROWS
to 1, and in this case checked iterators throw standard exceptions in case of error.
Conclusion
Checked iterators are a tool you should know about and use appropriately, at least during development.
References
- Bjarne Stroustrup: The C++ Programming Language.
- Herb Sutter, Andrei Alexandrescu: C++ Coding Standards.
- MSDN Library: Checked Iterators
Born in Kragujevac, Serbia. Now lives in Boston area with his wife and daughters.
Wrote his first program at the age of 13 on a Sinclair Spectrum, became a professional software developer after he graduated.
Very passionate about programming and software development in general.