成员函数指针为整数?

问题描述:

是否可以将虚拟地址作为成员函数指针的整数来获取?成员函数指针为整数?

我试过了。

 
void (AClass::*Test)(); 
Test = &AClass::TestFunc; 
int num = *(int*)&Test; 

但所有这一切都让我的jmp的虚拟地址的函数。我需要实际的功能虚拟地址。

尽管我无法确定是否有一种可移植的方式来执行此操作,但我通常建议使用静态包装函数为类方法提供此类外部访问。否则,即使成功了,您也会创建应用程序与该类实现的紧密耦合。

不,成员函数指针可能有a variety of sizes(从4-16字节或更多,具体取决于平台,请参阅文章中的表格),并且不能可靠地适应整数空间。这是因为虚拟函数和继承可能会导致编译器存储多条信息以调用正确的函数,因此在某些情况下不存在简单的地址。

如果这是我怀疑它,只是关闭增量链接。同时,你正在得到正确的答案。

我的另一个怀疑是TestFunc可能是virtual。对于获取地址的虚拟函数,VC++虚构了一个执行vtable查找的thunk,并给出了该thunk作为地址的指针。 (这确保了当实际的对象是派生类型更多的时候可以找到正确的派生函数,还有其他方法可以做到这一点,但是这允许这样的指针是单个指针并且简化了调用代码,代价是双倍当它们被调用时跳转)。打开程序的汇编语言输出,并查看结果;应该清楚发生了什么事情。

这里也是,你得到的是正确的答案,并且没有办法找到“实际”函数的地址。事实上,一个虚拟函数并没有命名一个实际函数,它命名了哪个派生函数适合于所讨论的对象。 (如果您不喜欢这种行为,请使该功能不是虚拟的。)

如果您确实需要实际功能的真实地址,则有两种选择。令人讨厌的是编写一些代码来扫描thunk以找出函数的vtable索引。然后查看相关对象的vtable以获取该函数。 (但请注意,取一个非虚函数的地址会给你实际调用的函数的地址,而不是一个thunk--所以你也不得不迎合这种可能性。指向虚拟函数的指针和指向非虚函数的指针是相同的。)

更简单的方法是创建一个包含每个虚函数代码的非虚函数,然后让每个虚函数调用非虚函数,虚拟功能。这给你和以前一样的行为。如果你想知道代码在哪里,可以使用非虚函数的地址。 (在任何一种情况下,这样做都很难很好地工作,这会很烦人,而且会是VC++特有的 - 但如果你愿意付出努力,你可能会发生这种情况)

+0

它不是虚拟的。尽管如此,它仍然是一项重要工作 – user230821 2010-05-28 13:56:35

+0

尝试关闭增量链接。在这种情况下,每个外部函数都会通过一些代码来调用它的实际地址。 (据推测,这样可以更好地重用以前链接中的数据,因为没有更改的模块只需要每次调用功能最多一次修复,而不是每次调用一次。) – 2010-05-29 18:14:27

我知道这是旧的,但因为没有有意义的主题答案,所以我去了。

有些事情需要首先考虑。 C++中的成员函数调用约定称为__thiscall。这个约定与__stdcall几乎相同,唯一明显的区别是,在进行有效调用之前,ECX被设置为调用其方法的对象的指针this

为了说明这一点,并在同一时间回答你的问题,让我们说,该类AClass宣布这样一个成员函数:int AClass::myFunction(int a, int b)而且我们有一个叫做aClassObjectAClass一个实例。 这里是做什么您最初问及“模拟”的aClassObject一个AClass::myFunction电话,一旦你获得原始指针相当hackish的方式:

// declare a delegate, __stdcall convention, as stated above 
typedef int (__stdcall *myFunctionDelegate)(int a, int b); 
// here's the 'hackish' solution to your question 
char myFunctionPtrString[10]; 
sprintf(myFunctionPtrString, "%d", &AClass::myFunction); 
int myFunctionPtr = atoi(myFunctionPtrString); 
// now let's call the method using our pointer and the aClassObject instance 
myFunctionDelegate myFunction = (myFunctionDelegate)myFunctionPtr; 
// before we make the call, we must put a pointer to aClassObject 
// in ECX, to finally meet the __thiscall calling convention 
int aClassObjectPtr = (int)&aClassObject; 
__asm{ 
    mov ecx, aClassObjectPtr 
} 
// make the call! 
myFunction(2, 3); 

当然并且,例如可以AClass类型的任何实例。

干杯,

Zozel