c++ - 调用C++成员函数指针: this-pointer gets corrupted

标签 c++ function pointers member void

我需要将一些成员函数指针转换为void*指针(因为我需要将它们压入Lua堆栈,但问题与Lua无关)。

我使用 union 来做到这一点。但是,当我将成员函数指针转换为 void* 并再次返回,然后尝试使用该类的实例调用该指针时,this 指针会损坏。奇怪的是,如果我将 void* 指针转换回 C 风格的函数指针,并将指向该类的指针作为第一个参数,这个问题就不会发生。

这是演示问题的一段代码:

#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;
}

这是输出:

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* 和(成员)函数指针之间的这种转换不符合标准,但奇怪的是,当将 void* 转换为C 风格的函数指针。

最佳答案

将这两行添加到您的代码中,答案将一目了然:

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();
};

当您在 Derived 上调用 Foo 时,this 指针必须指向 Base1::x。但是当您在 Derived 上调用 Bar 时,this 指针必须指向 Base2::j!因此,指向成员函数的指针必须包括函数地址和“调整器”,以更正 this 指针指向函数期望的正确类类型的实例 this 指针。

你丢失了调整器,导致 this 指针被随机调整。

关于c++ - 调用C++成员函数指针: this-pointer gets corrupted,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10977388/

相关文章:

c++ - 指向 const 重载成员函数的指针

代码可以编译,但在与游戏板一起运行时出现段错误

c - 为什么 fun(int *p) 不改变指针的值?

java - 痛饮 : How to rename generated Java code according to a regex?

c++ - 解析 ISO 8601 持续时间

c++ - boost 属性 write_json 不正确的行为

c++ - 分解数字时输出中的额外 "0"

c++ - 使用 vcpkg 下载依赖项而不创建 dll

php - 在方法中使用 require_once

javascript - JavaScript 中的函数调用