STL containers crash when empty

A few months ago, i got an issue with my code when i switched it from windows to Linux. On my STL containers, a call to clear() for exemple on an empty container crashed my program. To prevent that, i had to add a (size()>0) test before each "dangerous" access, and assumed that this was due to the implementation of STL on Linux.
Today, i got the same problem on Windows (VC++2005) for one of my containers.
The following code triggers it (NameMap is a std::map<std::string,Equipment*>) :
1
2
3
4
5
6
for(NameMap::iterator it = nameMap.begin(); it!=nameMap.end(); ++it){
	Equipment * const ptr = it->second;
	it->second = NULL;
	delete(ptr);
}
nameMap.clear();

The crash occurs on the line of the for, of on the line of the clear() if i comment the for.

Is there a reason for such code to crash on an empty container?
I sounds like you have a memory corruption problem. You ought to be able to write code like:
1
2
3
for (NameMap::iterator it = nameMap.begin(); it != nameMap.end(); ++it)
	delete it->second;
nameMap.clear();
without any concern of failure.
I would be tempted to examine where NameMap comes from. Is it a reference? Has the object it refers to gone out of scope?
As the others have said, a call to clear() on an empty container will not cause a program to crash. Something else is causing your program to crash and the call to clear() is just triggering it.
it would be interesting to find out what type of crash - to say "crash" is a bit vague.
Some details about the crash on windows :

The crash is an access violation at adress 0. For the line
for(NameMap::iterator it = nameMap.begin(); it!=nameMap.end(); ++it){,
It occurs in iterator _xtree::begin()

There are my data type declarations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Descripteur d'un equipement
*/
typedef struct Equipment{
	static const std::string NODENAME;
	//Nom del'equipement
	std::string name;
        //other members...
        //.....
	//construction depuis un noeud xml
	Equipment(const TiXmlElement * RESTRICT);
	class Store{
	public:
		static const std::string const NODENAME;
		const Store& operator =(const TiXmlElement * RESTRICT);
		~Store();
		/**
		* Container pour acces par nom
		*/
		typedef std::map<std::string, Equipment*> NameMap;
		static Equipment::NameMap nameMap;
	private:
		void clear();
	};
	static Store store;
}Equipment;


For now, i don't fill the map, so the crash occurs when i exit, at the liberation of the allocated Equipment(s) in Equipment::Store::clear(), called in Equipment::Store destructor
Hi ,
In the line

Equipment(const TiXmlElement * RESTRICT);

What is TiXmlElement ?
A class used by tinyxml library. I'm loading my map from an xml config file
Another detail. in my assignment operator for Equipment::Store, i call Equipment::Store::clear() before trying to load from my xml file, and it doesn't crash,with the map also empty.

So this must be a destruction order issue with my static data somewhere. If i remove the static keyword for nameMap, i don't seem to have the problem anymore.

Can a static member of a class (the map in Store) be destroyed before a static object of the class (the Store)? That seems strange
Last edited on
NameMap stores raw pointers. How do you manage the lifetime of these objects? Why are you not using a shared_ptr?

Why all the static objects?
I allocate Equipments in Store constructor, store their pointers in the map, and free them in store::clear(), which is called at the start of Store's assignmeent operator and in it's destructor.

Actually, i keep pointers due to some previous behaviour of the code. I could store Equipment directly in my map and not worry about allocation and liberation.

Why not shared_ptr? Because i don't know everything yet, but i'll add that to my "to study" list :)

About the use of static objects, for lots of data types i defined, i have only one container of this type in the whole application, so i like to allocate the container as a static member of the contained object.
I used to do
1
2
typedef struct myType{...} myType;
container<myType> typeContainer; //global container variable... 

Now i prefer to do
1
2
3
4
typedef struct myType{
...
static Container<myType> container; //not global anymore, and i prefer the new variable name myType::Container
} myType;

You may be invoking a copy constructor or assignment operator on your Equipment or Store class. Try making the copy constructor and assignment operator for both classes private and see if that gives you any hints. If it no longer compiles, it a good indication you were calling delete on the same pointer twice.

Non-const class static and global data are a strong code smell, indicative of bad design. They are functionally equivalent; the static member data is just encapsulated in a class namespace.

Use a singleton if you must, but this is not a case where a singleton should be necessary. Are you just trying to avoid passing the object around?
Topic archived. No new replies allowed.