std::vector::push_back is dereferencing an uninitialized pointer

Started by
3 comments, last by CDProp 14 years, 5 months ago
This is definitely very weird. I'm using OpenSceneGraph, and I'm trying to add a node as a child of another node using their osg::Node::addChild() method. The osg::Node has a list of parents and a list of children, each implemented as a std::vector<osg::Node*>. So, when I add a child to a parent, the parent first adds the child to its list of children, and then it calls on the child's addParent() method. Pretty straight-forward. For some reason, with one of the nodes, the vector throws an exception in debug mode during the addParent() step. The stack trace looks like this (edit - it was way too long, horizontally, so I edited out the parameter lists and line numbers from the following stack trace to make it easier to read):

	msvcp90d.dll!std::_Container_base_secure::_Orphan_all()
 	osg55-osgd.dll!std::vector<>::_Insert_n()
 	osg55-osgd.dll!std::vector<>::insert()
 	osg55-osgd.dll!std::vector<>::push_back()
 	osg55-osgd.dll!osg::Node::addParent()
 	osg55-osgd.dll!osg::Group::insertChild()

And I stepped through it, and what's happening is, it seems to want to reallocate the internal buffer, probably because this is the first time adding anything to the vector, and (I'm guessing) the vector's initial capacity is zero. And then it needs to invalidate all the iterators (what iterators? the begin and end iterators, maybe? I'm not sure). So, it calls _Orphan_all(). Once it gets into _Orphan_all(), it simply uses a for-loop to cycle through the iterators. It looks like this:

for (_Iterator_base **_Pnext = (_Iterator_base **)&_Myfirstiter; *_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter)
	(*_Pnext)->_Mycont = 0;



So, each cycle of the loop, it just sets _Mycont to 0, and then steps to the next iterator using the expression *_Pnext = (*_Pnext)->_Mynextiter. The problem is, the loop breaks when the *_Pnext != 0 test fails, right? Well, there's an iterator in this list with an unitialized Mynextiter. So, if I step through this loop for a few cycles, eventually the value of (*_Pnext) becomes 0xcdcdcdcd, and kaboom. I can definitely see why that'd be a problem. Does anyone have any guesses as to why this is happening?
Advertisement
Typically, errors from the standard library are manifestations of bad use, such as calling a function on an uninitialised/deleted vector or possibly memory corruption.

The value 0xcdcdcdcd is a special memory pattern. Try googling it for more info. This might give you a hint as to where to start.

Quote:
And then it needs to invalidate all the iterators (what iterators? the begin and end iterators, maybe? I'm not sure). So, it calls _Orphan_all().

That is "iterator debugging". The container knows all its iterators, so it can mark them invalid. This way, use of invalid iterators can be detected. It can be disabled.
Thanks. I'm stumped, though. I can't seem to find any misuse. I placed the call to parentNode->addChild() directly after the initialization of the child node. So, it looks like this (psuedocode):

 Node *child = new Node;parent->addChild(child);


The "parent" Node is able to successfully add the "child" to its list of children. The trouble occurs when the parent calls child->addParent(this).

So, I'm trying to think of what could be happening in between these two lines of code to cause the problem. Like I said before, the Parent List is a member of the Node class, and it is a vector of nodes, and nothing is being done to this vector in the Node's constructor or anything like that. So, it's just the vector's default constructor being called, and nothing else. In fact, no line of code touches this parent list vector until the addParent method is called.

grr.

edit - I realize there is little anyone can do to help in this case, as I am merely providing psuedo-code to a library that most of you are unfamiliar with. I guess I'm just venting, or something. If I gave you the exact source code, it'd just be confusing, because it's not quite that simple. I guess my question is...if something is happening to corrupt that vector, it can't be the vector's default constructor doing it to itself, right? It has to be something that is done in between the creation of the vector and its first use of push_back. Either that, or maybe some other buffer is being overrun somewhere, and is overwriting something. I don't know.
I'd double check to make sure that all your source files are using the same settings as each other and any libraries you're using. The only time I've seen something like that was when somehow one source file disable iterator debugging and the rest of the project hadn't.
Ok, bless you guys. I'll look into that.

This topic is closed to new replies.

Advertisement