Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ "this" doesn't match object method was called on

I have come across what seems like a really annoying bug running my C++ program under Microsoft Visual C++ 2003, but it could just be something I'm doing wrong so thought I'd throw it out here and see if anybody has any ideas.

I have a hierarchy of classes like this (exactly as is - e.g. there is no multiple inheritance in the real code):

class CWaitable
{
public:
    void WakeWaiters() const
    {
        CDifferentClass::Get()->DoStuff(this);  // Breakpoint here
    }
};

class CMotion : public CWaitable
{
   virtual void NotUsedInThisExampleButPertinentBecauseItsVirtual() { }
};

class CMotionWalk : public CMotion
{ ... };

void AnnoyingFunctionThatBreaks(CMotion* pMotion)
{
    pMotion->WakeWaiters();
}

Okay, so I call "AnnoyingFunctionThatBreaks" with a "CMotionWalk" instance (e.g. the debugger says it's 0x06716fe0), and all seems well. But when I step into it, to the breakpoint on the call to "DoStuff", the 'this' pointer has a different value to the pMotion pointer I called the method on (e.g. now the debugger says one word higher - 0x06716fe4).

To phrase it differently: pMotion has the value 0x06716fe0, but when I call a method on it, that method sees 'this' as 0x06716fe4.

I'm not just going mad am I? That is weird, right?

like image 794
andygeers Avatar asked Mar 21 '09 10:03

andygeers


2 Answers

I believe you are simply seeing an artifact of the way that the compiler is building the vtables. I suspect that CMotion has virtual functions of it's own, and thus you end up with offsets within the derived object to get to the base object. Thus, different pointers.

If it's working (i.e. if this isn't producing crashes, and there are no pointers outside the objects) then I wouldn't worry about it too much.

like image 172
Michael Kohne Avatar answered Sep 24 '22 07:09

Michael Kohne


Is CMotion class is deriving some other class also which contains a virtual function? I found that the this pointer does not change with the code you posted, however it changes if you have the hierarchy something like this:

class Test
{
public:
    virtual void f()
    {

    }
};

class CWaitable 
{
public:
    void WakeWaiters() const
    {
        const CWaitable* p = this;
    }
};

class CMotion : public CWaitable, Test
{ };


class CMotionWalk : public CMotion
{
public:
 };



void AnnoyingFunctionThatBreaks(CMotion* pMotion)
{
    pMotion->WakeWaiters();
}

I believe this is because of the multiple inheritance for CMotion class and the vtable pointer in CMotion which points to Test::f()

like image 36
Naveen Avatar answered Sep 25 '22 07:09

Naveen