Release-mode only falure when comparing STL list::iterator-s -- More info

Release-mode only falure when comparing STL list::iterator-s -- More info

Post by Ivan Vecer » Fri, 14 Apr 2006 00:56:11



: I'm coming out of one of those painful debugging sessions with an error
: appearing only in release mode. Somehow a library- or
compiler-generated
: runtime check fails only in release mode - and it vaguely looks like a
: check made by the STL implementation [reason for posting it here].
: I'm using Visual Studio 2005 with the included STL implementation.
: {the same code works flawlessly using gcc/Xcode and their STL}
...
: //// DATA STRUCTURES:
:
: typedef std::pair<float,float> Pos;
: struct Bone { /*...*/ }; // a link between joints
:
: struct Skeleton
: {
: typedef std::list<Bone> Bones;
: Bones bones;
:
: //for each Joint (given by a pos) keep a list of connected bones:
: typedef std::vector<Bones::iterator> JointBones;
: typedef std::map<Pos,JointBones> Joints;
: Joints joints;
: };
:
: typedef Skeleton::Bones::iterator BoneI;
:
:
: //// FAILING FUNCTION:
:
: BoneI getNextBone( Skeleton& skel, BoneI const link, Pos const curPos )
: {
: //-> test a potential candidate bone to return:
: BoneI const pong = *data.skel.joints[ curPos ].begin();
: bool ok1 = ( &*link == &*pong ); // always works [ 0 in this case ]
: bool ok2 = ( link==pong ); //CRASH in release build only...
: }

I traced the problem further, and I have an explanation for the cause.
I said I had only one instance of "Skeleton", but this was not totally
true: There is a function that initializes the instance of Skeleton
and returns it using the following idiom:
void generateSkeleton( ..... , Skeleton& out_skel )
{
Skeleton skel; // local temporary

// ... do stuff to fill-up skel ... could fail/throw

//Success -> send out the skeleton we have built:
out_skel.bones.swap( skel.bones );
out_skel.joints.swap( joints.bones );
}
Result: out_skel.joints contains iterators to elements of the
std::list<Bones> that was previously in skel.bones (but was
simultaneously swapped with out_skel.bones).

So now, does this 'swap' with subsequent use of iterators stored
in out_skel.joints trigger undefined behavior according to the
C++ standard ?
It might be a corner case.

But now, why do the built-in checks accept this in debug mode,
but reject it in release mode only ?

This inconsistency has caused me a lot of hassle...

Regards,
Ivan

--
http://www.yqcomputer.com/ ;- email contact form