Home > Articles > Programming > C/C++

C++ Tip #83: Use a Checked STL Implementation

  • Print
  • + Share This
In C++, it's all too easy to make iterator mistakes, and you may not even detect them when compiling and running your program. That's the bad news. The good news is that you don't have to run blind. There are tools for checking your code for these errors, and this chapter will tell you how to use them.
This chapter is from the book

In Brief

Safety first (see Item 6): Use a checked STL implementation, even if it's only available for one of your compiler platforms, and even if it's only used during pre-release testing.

Discussion

Just like pointer mistakes, iterator mistakes are far too easy to make and will usually silently compile but then crash (at best) or appear to work (at worst). Even though your compiler doesn't catch the mistakes, you don't have to rely on "correction by visual inspection," and shouldn't: Tools exist. Use them.

Some STL mistakes are distressingly common even for experienced programmers:

  • Using an invalidated or uninitialized iterator: The former in particular is easy to do.
  • Passing an out-of-bounds index : For example, accessing element 113 of a 100-element container.
  • Using an iterator "range" that isn't really a range: Passing two iterators where the first doesn't precede the second, or that don't both refer into the same container.
  • Passing an invalid iterator position: Calling a container member function that takes an iterator position, such as the position passed to insert , but passing an iterator that refers into a different container.
  • Using an invalid ordering: Providing an invalid ordering rule for ordering an associative container or as a comparison criterion with the sorting algorithms. (See [Meyers01] §21 for examples.) Without a checked STL, these would typically manifest at run time as erratic behavior or infinite loops, not as hard errors.

Most checked STL implementations detect these errors automatically, by adding extra debugging and housekeeping information to containers and iterators. For example, an iterator can remember the container it refers into, and a container can remember all outstanding iterators into itself so that it can mark the appropriate iterators as invalid as they become invalidated. Of course, this makes for fatter iterators, containers with extra state, and some extra work every time you modify the container. But it's worth it—at least during testing, and perhaps even during release (remember Item 8; don't disable valuable checks for performance reasons unless and until you know performance is an issue in the affected cases).

Even if you don't ship with checking turned on, and even if you only have a checked STL on one of your target platforms, at minimum ensure that you routinely run your full complement of tests against a version of your application built with a checked STL. You'll be glad you did.

  • + Share This
  • 🔖 Save To Your Account