调用 C++ 成员函数指针:此指针已损坏
Calling a C++ member function pointer: this-pointer gets corrupted
我需要将一些成员函数指针转换为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
指针随机调整。
奇怪的是,在这里(在VS2005下),第一个和第三个调用工作正常,但第二个(使用conv3)失败,这被破坏了。
,在您的实现中,指针到成员函数类型的实例的前 size(void*)
个字节恰好void (test::*) ()
在这种情况下是内存中函数的地址。作为实现细节,该函数是可调用的,就好像它是一个以 this
作为第一个参数的自由函数一样。这就是为什么conv3
似乎有效。
但是,当尝试将前 sizeof(void*)
个字节复制到指针到成员函数类型的不同实例中时,您的运气已经用完了。conv2
其余部分的未初始化垃圾,一旦被解释为初始代码地址之后指向成员函数的指针的其余部分,就会出错。我怀疑那里有一些标志和偏移量,以记录有关虚函数以及多重和虚拟继承的信息。当这些信息不正确时,事情就会出错。
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 为什么C中的通用链表中存储的数据已损坏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 变量周围的堆栈'...'已损坏
- 运行时检查失败 #2 变量"A"周围的堆栈已损坏
- 两个垫子的 OpenCV 数据是相同的,但使用 Mat::at 检索时的值已损坏
- 运行时检查失败 #2 - 变量"e"周围的堆栈已损坏。发生
- 变量周围的堆栈'sortArray'已损坏
- 变量周围的堆栈'folderPath'已损坏
- 在为 iOS 构建 aws-sdk-cpp 时,cmake 上的 CXX 编译器错误已损坏
- 运行时检查失败 #2 - 变量周围的堆栈'...'已损坏
- AES-128 CFB-8解密的前16个字节已损坏
- 运行时检查失败 #2 - 变量"l1"周围的堆栈已损坏
- C++:此代码可以编译,但引发运行时检查失败 #2 - 围绕变量周围的堆栈'num'已损坏。发生
- 图像在本地主机上显示已损坏
- 检查工作正常的 CXX 编译器:/cygdrive/c/cygwin64/bin/clang++ -- 已损坏
- C++指针:数组的堆栈已损坏
- 指针函数参数已损坏,堆栈已损坏
- 从函数返回时指针已损坏
- 调用 C++ 成员函数指针:此指针已损坏