简体   繁体   中英

C++: Strange virtual member function pointers in Visual Studio 2013

I am just puzzled by the following:

struct InterfaceABC {
    virtual int printPolymorphic(int a) {
        return a;
    }
}

struct WithInterfaces : public InterfaceABC {
    virtual int printPolymorphic(int a) { return a; }
};

When I now do:

address = &WithInterfaces::printPolymorphic;

I get this in the debugger:

0x012e52a9 {unittests.exe![thunk]:MockMe::WithInterfaces::`vcall'{4,{flat}}' }'}

BUT, the following invokation will not land there:

((InterfaceABC*) new WithInterfaces())->printPolymorphic(3);

After a day of effort I found out how to "reliably" (famous last words) get the real virtual address using C++ code, which gives me:

0x012e6ece {unittests.exe!MockMe::WithInterfaces::printPolymorphic(int)}

So what do we have here?

WithInterfaces().printPolymorphic(3)

Will be calling

0x012e6ece {unittests.exe!MockMe::WithInterfaces::printPolymorphic(int)}

And so will

((InterfaceABC*)new WithInterfaces())->printPolymorphic(3);

...

Visual Studio implements the stub function justfor me :) huh? I feel flattered... but

address = &WithInterfaces::printPolymorphic;

this will not at all give you the function address. It will give you an address to a function that is never called and can never be called without hackery.

Anyone has some great ideas as to why this is? And maybe also some ideas about how to REALLY get the real address without writing about 100 lines scary C++ madness that probably no one but me understands from all the people that will be reviewing the code? That is, in a standard compliant way...

Taking the address of WithInterfaces::printPolymorphic gives you back a thunk that, when invoked, dispatches to the correct function to call based on the type of the object.

If you call a virtual member function on an object, the compiler emits code to look up a pointer to the correct implementation in the virtual function table ( vtable ) of the object and then invokes that function.

A pointer to a virtual member function encapsulates this behavior, which you made explicit by looking at the generated thunk.

It will give you an address to a function that is never called and can never be called without hackery.

The logic for it, however, is contained in every single call to a virtual function.

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