Topic: Safe STL
Author: horstman@jupiter.SJSU.EDU (Cay S. Horstmann)
Date: 1995/11/10 Raw View
I designed a small but useful enhancement to make STL safer to use.
Safe STL catches many typical STL programming errors at runtime (and a
few at compile time).
The most current version of this code is available on the World Wide
Web:
http://www.mathcs.sjsu.edu/faculty/horstman/safestl.html
The material is free.
Here is some background information.
= What it does
When you compile and link your code with Safe STL, iterators are
instrumented to be checked whenever they are used. Container
operations (such as assignment, insertion, removal, etc.) update all
iterators attached to a container.
If an error is detected, then an assertion failure is raised. Of
course, checking and updating the iterators takes time. For release
versions of your code, you would probably want to go back to the
unchecked version of STL. For that reason, the interface of Safe STL
is purposefully left the same as that of regular STL. It would be an
easy matter to add public member functions to the iterators
that check their status, but I believe that it is best not to develop
yet another nonstandard template library.
Safe STL works better than a debugger or BoundsChecker for a number of
reasons. If your code dies because of a pointer error that is the
consequence of an STL usage error, the debugger will break deep in the
bowels of STL code which is usually less than illuminating. If your
code gets in an infinite loop because of an STL usage error,
BoundsChecker will not actually complain. Some STL usage errors
cause subtle inconsistencies in the STL data structures that will not
lead to immediate failure.
= Some typical errors that Safe STL catches
* Runaway iterators
list<int> a;
list<int> b;
// ...
list<int>::iterator p
= find(a.begin(), b.end(), 100);
// oops, should have been a.end()
if (p != a.end()) a.erase(p);
This code will loop forever when a.end() is reached.
Of course nobody would make such a dumb coding mistake.
I did several times, when I did some cut and paste and was sloppy
about updating the pasted code.
* Muddled iterators
list<int> a;
list<int> b;
list<int>::iterator pa = a.begin();
b.erase(pa);
In the HP implementation, this will erase the first element of a, but
reduce the length of b! Eventually, but not immediately, that will
lead to weird behavior.
* Past the end iterators
list<int>::iterator p
= find_if(a.begin(), a.end(), condition);
cout << *p; // an error if p is past the end
* Uninitialized iterators
list<int>::iterator p;
cout << *p; // an error
* Iterators to erased elements
list<int>::iterator p = a.begin();
list<int>::iterator q = p;
a.erase(q);
cout << *p; // an error
* Iterators to moved elements
vector<int>::iterator p = b.begin();
b.reserve(1000);
cout << *p; // maybe an error
* Iterators to destroyed containers
list<int>* pl = new list<int>;
list<int>::iterator p = pl->begin();
delete pl;
cout << *p; // an error
= How to use it
Get the complete version of regular STL by ftp from butler.hpl.hp.com.
Put all regular STL files in a directory, e.g. /stl. Put the .h files
from the Safe STL distribution
algobase.h
vector.h
deque.h
list.h
tree.h
into a separate directory, e.g. /safestl. Then put that directory into
the directory search path, BEFORE the directory that contains the
regular STL. Then compile and link your application.
Once your application is debugged, simply remove /safestl from the
include path and rebuild the application.
[Moderator's note: this article is crossposted; followups will go to
comp.lang.c++ by default. If you do post a followup, please edit the
newsgroups line if appropriate. The comp.std.c++ policy is to
discourage crossposting in general, but not to prohibit it. mha]
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]