C ++ element function pointer call: this pointer is damaged

I need to convert some pointers to member functions to pointers void*(because I need to push them to the Lua stack, but the problem is not related to Lua).

I do this with help union. But when I convert the pointers of a member function to void*and vice versa, and then try to call a pointer with an instance of the class, the pointer thiswill get corrupted. Strange, this problem does not occur if I convert the pointer void*back to a pointer to a C-style function with a pointer to the class as the first parameter.

Here is a piece of code that demonstrates the problem:

#include <iostream>
using namespace std;

class test
{
    int a;

    public:
        void tellSomething ()
        {
            cout << "this: " << this << endl;
            cout << "referencing member variable..." << endl;
            cout << a << endl;
        }
};

int main ()
{
    union
    {
        void *ptr;
        void (test::*func) ();
    } conv1, conv2;

    union
    {
        void *ptr;
        void (*func) (test*);
    } conv3;

    test &t = *new test ();

    cout << "created instance: " << (void*) &t << endl;

    // assign the member function pointer to the first union
    conv1.func = &test::tellSomething;

    // copy the void* pointers
    conv2.ptr = conv3.ptr = conv1.ptr;

    // call without conversion
    void (test::*func1) () = conv1.func;
    (t.*func1) (); // --> works

    // call with C style function pointer invocation
    void (*func3) (test*) = conv3.func;
    (*func3) (&t); // --> works (although obviously the wrong type of pointer)

    // call with C++ style member function pointer invocation
    void (test::*func2) () = conv2.func;
    (t.*func2) (); // `this' is the wrong pointer; program will crash in the member function

    return 0;
}

This is the result:

created instance: 0x1ff6010
this: 0x1ff6010
referencing member variable...
0
this: 0x1ff6010
referencing member variable...
0
this: 0x10200600f
referencing member variable...
zsh: segmentation fault (core dumped)  ./a.out

​​ (GCC)? , void* (member) , , void* C.

+5
3

, :

cout << "sizeof(void*)=" << sizeof(conv1.ptr) << endl;
cout << "sizeof(test::*)=" << sizeof(conv1.func) << endl;

. :

class Base1
{
 public:
 int x;
 void Foo();
 Base1();
};

class Base2
{
 public:
 float j;
 void Bar();
 Base2();
};

class Derived : public Base1, public Base2
{
 Derived();
};

Foo Derived, this Base1::x. Bar Derived, this Base2::j! - , "", this, , this.

, this .

+5

, ( VS2005) 1- 3- , ( conv3) .

+1

, size(void*) --- void (test::*) () , , . , this . conv3, , .

However, your luck ended up trying to copy these first sizeof(void*)bytes to another instance of a member pointer type. The uninitialized garbage in the rest conv2, once interpreted as the rest of the pointer-member function after the source code, did something wrong. I suspect there are several flags and offsets there to record information about virtual functions and multiple and virtual inheritance. When this information is incorrect, everything goes wrong.

+1
source

All Articles