Skip to main content
gamedev.net
🔒 Locked

Problem with std::map

Started by starfleetrp Aug 14, 2006 at 2:13 PM 12 replies 1.3k views
Original Post
starfleetrp
starfleetrp
Hi, I am having some trouble with this section of code because it seems to be causing a memory read error. I am not sure what the problem is. Here is my code.

mObjects = a std::map
void Node::deleteAllObjects()
{
	std::string string;
	std::stringstream sstream;
	sstream << mObjects.size();
	sstream >> string;

	MAP_STRING2MOVABLEOBJECT::iterator i, iend;
	iend = mObjects.end();
	MessageBox(NULL,string.c_str(),"Size of mObjects",MB_OK);
	for (i = mObjects.begin(); i != iend; ++i)
	{
		///i->second->setParent(0);
		MessageBox(NULL, "Node::deleteAllObjects() called", mName.c_str(),MB_OK);
		delete i->second;
		//i->second->_notifyDetachment();
	}
    mObjects.clear();
}


Now ill tell you kinda what the message boxs say in order Size of mObjects = 1 Node::deleteAllObjects() called (now the destructor of the object is a called displaying its name in a msgbox) Node::deleteAllObjects() called ; im not sure why its doing this again now I get the error because im trying to access and invalid i->second address. Please help me spot what im doing wrong. Note: I have tried to do this without attatching an object to this node and no errors happen [Edited by - starfleetrp on August 14, 2006 3:56:25 PM]
NotAYakk
NotAYakk
Write:
template<typename any_map_type>void MsgBoxNumOfObjects( any_map_type const& Objects ) {	std::string string;	std::stringstream sstream;	sstream << Objects.size();	sstream >> string;	MessageBox(NULL,string.c_str(),"Size of map",MB_OK);}


Now, in that loop, do the following::

	for (i = mObjects.begin(); i != iend; ++i)	{		MsgBoxNumOfObjects(mObjects);		///i->second->setParent(0);		MessageBox(NULL, "Node::deleteAllObjects() called", mName.c_str(),MB_OK);		delete i->second;		MsgBoxNumOfObjects(mObjects);		//i->second->_notifyDetachment();	}


What do you get?

Second, can you sketch what i->second does in it's destructor?
starfleetrp
starfleetrp
Ok well the mObjects contains a pointer to a *MovableObject in second

so the ~MovableObject is just:
{
MessageBox(NULL,mName.c_str(),"~MovableObject ",MB_OK);
}
which is called when the MovableObject is deleted

and oh yeah the Nodes destructor calles the deleteObjects function

Now with your modifications to the loop I now get....
~Node "Ship Hull "
Node::deleteObject Called "Ship Hull"
Map Size 1
~Movable Object Ship1 Entity
Map Size 0
Node::deleteObject Called "Ship Hull"
Map Size 0
ERROR
-- The done with call messagebox does not show up (newly added)

note I also changes a bit of the function besides the loop. I got rid of the inital Objects size and move up the deleleObject messagebox so now its like
	//std::string string;	////std::stringstream sstream;	//sstream << mObjects.size();	//sstream >> string;	MAP_STRING2MOVABLEOBJECT::iterator i, iend;	iend = mObjects.end();	//MessageBox(NULL,string.c_str(),"Size of mObjects",MB_OK);	//MsgBoxNumOfObjects(mObjects);	for (i = mObjects.begin(); i != iend; ++i)	{		MessageBox(NULL, "Node::deleteAllObjects() called", mName.c_str(),MB_OK);		MsgBoxNumOfObjects(mObjects);		///i->second->setParent(0);		delete i->second;		MsgBoxNumOfObjects(mObjects);		//i->second->_notifyDetachment();	}	MessageBox(NULL,"Done with the call","",MB_OK);    mObjects.clear();


NotAYakk
NotAYakk
And finally:
Quote:
Map Size 1
~Movable Object Ship1 Entity
Map Size 0


Deleting a movable object changes the size of your map!

I do not believe:
Quote:
Ok well the mObjects contains a pointer to a *MovableObject in second

so the ~MovableObject is just:
{MessageBox(NULL,mName.c_str(),"~MovableObject ",MB_OK);}

which is called when the MovableObject is deleted


that "delete i->second" only executes the above code. What is the class heirarcy of a MovableObject? Does it inherit from or contain any classes with non-trivial destructors? Is the destructor virtual, and does anything inherit from it that contains non-trivial destructors?

Does any of the above destructors "automatically remove itself from the map, to be safe"?

However you are doing it -- either explicitly, or accidentally via memory corruption (unlikely, honestly) -- you are invalidating your iterator by removing the node from the map while you are iterating over it.

This makes "++i" execute undefined behaviour -- you are not allowed to use an invalidated iterator. The undefined behaviour, in this case, happens to be "I give you an invalid pointer when you call i->second".
starfleetrp
starfleetrp
Ok the MovableObjects destructor is virtual and the object that is inherieted is an *Entity. The entity destructor is also virtual but does nothing at the moment.

Edit: I dont know I just did a re-build of the whole project instead of a build and now it works. Something must have been really messed up with VC++.
hplus0603
hplus0603
It seems to me as if you don't know how to use the debugger. All those calls to MessageBox gives it away :-)

You should instead set a breakpoint at the points where you want to inspect variables. When the code stops, just look at them in the Auto window (or type their name into the Watch window). Also, stepping line by line with F10 (and into functions with F11) is very useful when figuring out what's going wrong, especially combined with breakpoints in object destructors. (Unfortunately, F11 doesn't work for stepping into a deleted objects destructor, due to a bug in VS 2003 and 2005)
enum Bool { True, False, FileNotFound };
starfleetrp
starfleetrp
I was using the messageboxs so I could see the objects name instead since every one has its own indivvidual name. This way it is better than a break point because I can see what object was messing up.

[Edited by - starfleetrp on August 14, 2006 11:43:55 PM]
taby
taby
As an aside:

Some delete functions return iterators one past the element you just deleted. ie:


for(iter = container.begin(); iter != container.end(); /* do nothing here */ )
{

if(blah)
iter = container.delete(iter); // delete element and move to next valid element
else
iter++; // ignore element and move to next valid element

}
jpetrie
jpetrie
Quote:

I was using the messageboxs so I could see the objects name instead since every one has its own indivvidual name. This way it is better than a break point because I can see what object was messing up.


In other words, you don't know how to use the debugger? You can use the "watch window" to examine the contents of variables, including the individual name of the individual object. Also, you can use tracepoints instead of Messageboxs to get essentially the same result as "MessageBox debugging" without having to recompile your code. I suggest you spend some time exploring the features of your debugger because it is an essential tool to know.

Of course, this assumes you are using an IDE with a decent debugger (Visual Studio) and not some terrible broken debugger like the one with Dev-C++.
jpetrie
jpetrie
Quote:

I'd use OutputDebugString(), and if you want execution to halt, use DebugBreak() or just place breakpoints.

Breakpoints and tracepoints are both superior, if available; they don't require recompilation.
starfleetrp
starfleetrp
Your right, I did not know about the "watch box" and for some reason I can not even seem to find the window. I know I sound pretty stupid (im sure I also am). I tried to google arround for it and the results I found just simply state what is does and how to use it. However that is assuming that I can see it, which I cant. Can someone please tell me what I am doing wrong. I am using VC++ 2003
NotAYakk
NotAYakk
From the menu:
Debug->Windows->Watch

In 2003, this only shows up while you are debugging a program from within the debugger.

The windows that spawn will be dockable.
Extrarius
Extrarius
Note that using the debugger in 'release' mode can produce unexpted results (breakpoints might be ignored, the debugger will jump the 'currently executing line' all over the place even when single stepping [it might even go backwards such as line 5 then 6 then 7 then 6 then 5 then 8], etc) in VS 2003 and prior (don't know about 2005)
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.