简体   繁体   中英

Invalid ESP when using multiple inheritance in C++ (VS2005)

I've been making a game which uses the Box2D physics engine, and I've come across some weirdness with the stack pointer (ESP) and multiple inheritance. I've managed to reproduce it in a minimal amount of code, and it seems that the order in which I declare the classes to be used in multiple inheritance seems to dictate whether the program crashes or not.

#include <iostream>
#include <string.h>

using namespace std;

class IPhysicsObject
{
public:
    virtual void Collide(IPhysicsObject *other, float angle, int pos)=0;
};

class IBoardFeature
{
public:
    IBoardFeature(){};
    ~IBoardFeature(){};

    virtual bool OnAttach(int x){ return true; }
    virtual bool Update(int x, float dt)=0;
};

/*
class CScorezone : public IBoardFeature, public IPhysicsObject // this breaks !!!
class CScorezone : public IPhysicsObject, public IBoardFeature // this works !!!
*/
class CScorezone : public IBoardFeature, public IPhysicsObject
{
public:
    CScorezone(){}
    ~CScorezone(void){}

    virtual bool Update(int x, float dt)
    {
        return true;
    }

    virtual void Collide(IPhysicsObject *other, float angle, int pos)
    {
    }

    virtual bool OnAttach(int x){ return true; }
};


int main(int argc, char *argv[]) 
{
    CScorezone *scoreZone = new CScorezone();
    CScorezone *otherZone = new CScorezone();

    void *voidZone = scoreZone;
    IPhysicsObject *physZone = static_cast<IPhysicsObject*>(voidZone);
    physZone->Collide(otherZone, 10, 1);

    delete scoreZone;
    delete otherZone;

    // wait for user input
    int x;
    cin >> x;
    return 0;
}

Running this in debug mode 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.

When I step in to the following line of code:

physZone->Collide(otherZone, 10, 1);

I notice it's going into CScoreZone::OnAttach, not CScoreZone::Collide. Why is this? WHen I change the order of inheritance for CScoreZone, it works fine

class CScorezone : public IPhysicsObject, public IBoardFeature

I'm running on VS2005 SP2 (8.0.50727.768) on Windows XP. Any ideas?

You don't have to assign CScorezone* to void* and then cast it to IPhysicsObject* . Since CScorezone is-a IPhysicsObject you can simply assign to base pointer:

    IPhysicsObject *scoreZone = new CScorezone();
    IPhysicsObject *otherZone = new CScorezone();

You're also missing public virtual destructor in IPhysicsObject declaration.

Edit:

I a callback situation as you describe in the comments (going through some C api?) I'd use simple struct with a pointer to polymorphic type to avoid undefined casts, something like:

    // one more level of indirection
    struct cb_data
    {
        IPhysicsObject* target;
    };

    // callback function
    int callback( void* data )
    {
        const cb_data& cbd( *static_cast<cb_data*>( data ));

        return cbd.target->Collide( ... );
    }

The problem is that you cast the pointer to void* first. The compiler doesn't know then how to perform static cast for the pointer. It needs to change the pointer value during the cast if you use multiple inheritance to use second superclass virtual table. Just cast the pointer back to CScoreZone* before using static_cast.

Well, in your code you seem to be deliberately destroying the integrity of a hierarchical cast by using void * as an intermediate type in the cast. ScoreZone * is cast to void * first and then cast to IPhysicsObject * . What you get as the result is undefined behavior.

Why are you doing this? And what did you expect will happen?

Nikolai told you how to avoid casting in the first place with your example given. However if you do need to do a typecast, when working with objects always use dynamic_cast, which does runtime type checking.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM