C++ 调用C++;成员函数指针:此指针已损坏

C++ 调用C++;成员函数指针:此指针已损坏,c++,function,pointers,member,void,C++,Function,Pointers,Member,Void,我需要将一些成员函数指针转换为void*指针(因为我需要将它们推送到Lua堆栈,但问题与Lua无关) 我使用联合执行此操作。但是,当我将成员函数指针转换为void*并再次转换,然后尝试用类的实例调用指针时,此指针会损坏。更糟糕的是,如果我将void*指针转换回C风格的函数指针,并将指向类的指针作为其第一个参数,那么这个问题就不会发生 下面是一段演示问题的代码: #包括 使用名称空间std; 课堂测试 { INTA; 公众: 空出某物() { cout将这两行代码添加到您的代码中,答案就会很清楚:

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

我使用
联合执行此操作。但是,当我将成员函数指针转换为
void*
并再次转换,然后尝试用类的实例调用指针时,
指针会损坏。更糟糕的是,如果我将
void*
指针转换回C风格的函数指针,并将指向类的指针作为其第一个参数,那么这个问题就不会发生

下面是一段演示问题的代码:

#包括
使用名称空间std;
课堂测试
{
INTA;
公众:
空出某物()
{

cout将这两行代码添加到您的代码中,答案就会很清楚:

cout << "sizeof(void*)=" << sizeof(conv1.ptr) << endl;
cout << "sizeof(test::*)=" << sizeof(conv1.func) << endl;
派生的
上调用
Foo
时,此
指针必须指向
Base1::x
。但在
派生的
上调用
Bar
时,此
指针必须指向
Base2::j
!因此指向成员函数的指针必须同时包含函数的地址和“adjustor”用于更正
指针,指向函数期望作为
指针的正确类类型的实例


您正在丢失调整器,导致
这个
指针被随机调整。

奇怪的是,在这里(在VS2005下),第一次和第三次调用工作正常,但第二次调用(使用conv3)失败,导致该指针损坏。

在我看来,在您的实现中,第一次
大小(void*)
指向成员函数类型的指针实例的字节
void(测试::*)()
在本例中,正好是内存中某个函数的地址。作为实现细节,该函数可以调用,就像它是一个自由函数一样,将
this
作为第一个参数。这就是
conv3
似乎可以工作的原因


然而,当您尝试复制第一个
sizeof(void*)时,您的运气已经耗尽
字节输出到指向成员函数类型的指针的另一个实例中。
conv2
的其余部分中的未初始化垃圾,一旦被解释为指向成员函数的指针在初始代码地址之后的剩余部分,就会导致一些错误。我怀疑其中有一些标志和偏移,用于记录有关v的信息虚拟函数、多重继承和虚拟继承。当这些信息不正确时,就会出现问题。

是否检查了memfunptr的sizeof()值?在我的实现中,它大于sizeof(void*),作为一种猜测,VS2005对函数指针使用cdecl调用约定(因此参数在堆栈上传递),但成员函数的thiscall调用约定(因此被调用方希望在ECX中传递
this
)。因此,即使提供了正确的代码地址,也会阻止
conv3
工作。这正是我预期会发生的行为。好的,非常感谢,这说明了这一点。我现在使用另一个
union{struct{void*p1,*p2;}ptr;void(test:*func)(;}转换指针
。这种方法在任何情况下都有效吗?或者最好先查找成员函数指针的大小,然后决定使用多少个
void*
?我更喜欢第一种方法。@AlfredKrohmer:您可能只需将指针分配给成员函数,传递一个指向它的指针,并找出最佳方法管理资源。当然,如果您通过Lua传递一些
struct
,其中包含几个整数和一个指针,您不会试图计算出需要将多少
void*
添加到其内存中,并将其重新解释为多个
void*
?那么,指向成员函数的指针就是几个整数和一个指针。小心另外,在某些实现中,指向不同类型成员函数的指针大小不同。@Steve Jessop如果我正确理解David Schwartz的帖子,成员函数指针的
sizeof
通常是固定的,因为它包含函数指针和调整,并且可能只因平台而异。我不明白这与在Lua中传递
structs
有什么关系。我只想将成员函数指针作为
lightuserdata
推送,以便泛型处理函数可以回调成员函数(这已经非常有效)。@AlfredKrohmer:这取决于你所说的“通常”是什么意思"。在英特尔和MSVC编译器上,它不是固定的,指向不同类型成员函数的指针大小不同,取决于所涉及的继承。我不确定GCC上的情况。对于任何指向成员函数类型的特定指针,它肯定是固定的。它与结构有关的是,指向成员类型的指针与一种小型结构类型:实现决定(并隐藏)它拥有哪些数据成员,但它们仍在其中。
class Base1
{
 public:
 int x;
 void Foo();
 Base1();
};

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

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