Run-Time Check Failure #0 Fun Stadium

Started by
3 comments, last by SiCrane 12 years, 1 month ago
(C++, MSVC, DLLS and LIBS are being used)
Well, right to the issue!


This is called when you are finished with the class.

FORCEINLINE void
TriangleSoup::Release( )
{
// NOW: bad calling convention or stack mutililation
PhysicsAPIInternal()->RemoveFromSimulation( this );

delete this;
}

The commented line causes the following error:
"Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."

I don't really know why!

This code is run inside the game dll, TriangleSoup is in a lib and PhysicsAPIInternal is calling a global gotten from the physicssystem dll.


Here is some of the relavent sources truncated to important bits:

TriangleSoup.h

class TriangleSoup: public ICollide
{
void Link( OcTree< ICollide* >::Node* node );
const Vector< OcTree< ICollide* >::Node* >* GetLinks( );
void Unlink( );

void Release( );

private:
Vector< OcTree< ICollide* >::Node* > backlinks_; // broadphase backlinks
};

#include "trianglesoup.inl"


TriangleSoup.inl

FORCEINLINE void
TriangleSoup::Link( OcTree< ICollide* >::Node* node )
{
backlinks_.InsertBack( node );
}

FORCEINLINE const Vector< OcTree< ICollide* >::Node* >*
TriangleSoup::GetLinks( )
{
return &backlinks_;
}

FORCEINLINE void
TriangleSoup::Unlink( )
{
for( uint32 i = 0; i < backlinks_.GetCount(); ++i )
{
backlinks_[ i ]->RemoveObject( this );
}

backlinks_.RemoveAll();
}

FORCEINLINE void
TriangleSoup::Release( )
{
// NOW: bad calling convention or stack mutililation
PhysicsAPIInternal()->RemoveFromSimulation( this );

delete this;
}


PhysicsSystem.h

class IPhysicsSystemInternal
{
public:
virtual ~IPhysicsSystemInternal( ) { ; }

virtual void AddToSimulation( ICollide* collide ) = 0;
virtual void RemoveFromSimulation( ICollide* collide ) = 0;
};

class PhysicsSystem: public IPhysicsSystemInternal, public IPhysicsSystem
{
public:
PhysicsSystem( );
~PhysicsSystem( );

void AddToSimulation( ICollide* collide );
void RemoveFromSimulation( ICollide* collide );
};

// Internal Accessor
FORCEINLINE IPhysicsSystemInternal* PhysicsAPIInternal( )
{
extern IPhysicsSystem* _g_PhysicsSystemInstance;
Assert( _g_PhysicsSystemInstance );
return (IPhysicsSystemInternal*)_g_PhysicsSystemInstance;
}


PhysicsSystem.cpp


void
PhysicsSystem::AddToSimulation( ICollide* collide )
{
// link to octree
Extents extents;
collide->GetExtents( extents );
ocTree_.AddObject( collide, extents );

// add to simualted entities
simulatedCollides_.InsertBack( collide );
}

void
PhysicsSystem::RemoveFromSimulation( ICollide* collide )
{
// unlink from octree
collide->Unlink();

// remove from simulated entities
simulatedCollides_.FindFirstAndRemove( collide );
}


I'm not sure where to start here!
Thanks allot guys as usual.
Advertisement
Also, it only happenes when I use PhysicsAPIInternal() (which casts the global to a IPhysicsSystemInternal) because I declared the same methods in IPhysicsSystem (the public interface) and it works fine!

But now I have internals exposed.
...
Ok, a few things...
Does IPhysicsSystemInternal derive from IPhysicsSystem? No? Then why do you force it down that route with this cast:


extern IPhysicsSystem* _g_PhysicsSystemInstance;
Assert( _g_PhysicsSystemInstance );
return (IPhysicsSystemInternal*)_g_PhysicsSystemInstance;
.

C casts are BAD. Period. Use C++ casts. Chances are high that because you're forcing the pointer from type A to type B, where A not related to B, you've just screwed which virtual table you're actually pointing to.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Errors like this are making a pretty convincing argument to go back to c++ style casting.

Anyway, 'IPhysicsSystemInternal' does not inherit 'IPhysicsSystem' (ATM, but it is supposed to at some point) so you're right there.

'_g_PhysicsSystemInstance' is supposed to point to an instance of 'PhysicsSystem' casted to an 'IPhysicsSystem' for public access. Since 'PhysicsSystem' inherits them both, can't I cast the '_g_PhysicsSystemInstance' either way indiscriminately?

It seems not, but I'm pretty unsure why this is.

Thanks!
In this case you can use a dynamic_cast to get from one interface to the other. A C style cast will just reinterpret the address as the other interface, but with multiple interfaces the interfaces have different addresses for the same object.

This topic is closed to new replies.

Advertisement