C++ 获取成员函数的内存地址?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8121320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get memory address of member function?
提问by user541686
How do I get the absoluteaddress of a member function in C++? (I need this for thunking.)
如何在C++中获取成员函数的绝对地址?(我需要这个来重击。)
Member function pointers don't work because I can't convert them to absolute addresses (void *
) -- I need to know the address of the actual function in memory, not simply the address relative to the type.
成员函数指针不起作用,因为我无法将它们转换为绝对地址 ( void *
) —— 我需要知道实际函数在内存中的地址,而不仅仅是相对于类型的地址。
采纳答案by valdo
There exists a syntax to get the address of the member function in MSVC (starting from MSVC 2005 IMHO). But it's pretty tricky. Moreover, the obtained pointer is impossible to cast to other pointer type by conventional means. Though there exists a way to do this nevertheless.
存在获取 MSVC 中成员函数地址的语法(从 MSVC 2005 恕我直言)。但这很棘手。而且,获得的指针无法通过常规方式转换为其他指针类型。尽管有一种方法可以做到这一点。
Here's the example:
这是示例:
// class declaration
class MyClass
{
public:
void Func();
void Func(int a, int b);
};
// get the pointer to the member function
void (__thiscall MyClass::* pFunc)(int, int) = &MyClass::Func;
// naive pointer cast
void* pPtr = (void*) pFunc; // oops! this doesn't compile!
// another try
void* pPtr = reinterpret_cast<void*>(pFunc); // Damn! Still doesn't compile (why?!)
// tricky cast
void* pPtr = (void*&) pFunc; // this works
The fact that conventional cast doesn't work, even with reinterpret_cast
probably means that MS doesn't recommend this casting very strongly.
常规演员表不起作用的事实,即使reinterpret_cast
可能意味着 MS 不强烈推荐这种演员表。
Nevertheless you may do this. Of course this is all implementation-dependent, you must know the appropriate calling convention to do the thunking + have appropriate assembler skills.
不过你可以这样做。当然这都是依赖于实现的,你必须知道适当的调用约定来进行 thunking + 具有适当的汇编技能。
回答by HaPpY
try this. should let you cast anything to anything :)
尝试这个。应该让你把任何东西都投给任何东西:)
template<typename OUT, typename IN>
OUT ForceCast( IN in )
{
union
{
IN in;
OUT out;
}
u = { in };
return u.out;
};
then
然后
void* member_address = ForceCast<void*>(&SomeClass::SomeMethod);
回答by kreuzerkrieg
By default, C++ member functions use the __thiscall calling convention. In order to Detour a member function, both the trampoline and the detour must have exactly the same calling convention as the target function. Unfortunately, the VC compiler does not support a __thiscall, so the only way to create legal detour and trampoline functions is by making them class members of a "detour" class.
In addition, C++ does not support converting a pointer to a member function to an arbitrary pointer. To get a raw pointer, the address of the member function must be moved into a temporrary member-function pointer, then passed by taking it's address, then de-referencing it.Fortunately, the compiler will optimize the code to remove the extra pointer operations.
默认情况下,C++ 成员函数使用 __thiscall 调用约定。为了绕开成员函数,trampoline 和 detour 必须与目标函数具有完全相同的调用约定。不幸的是,VC 编译器不支持 __thiscall,因此创建合法的 detour 和 trampoline 函数的唯一方法是使它们成为“detour”类的类成员。
此外,C++ 不支持将指向成员函数的指针转换为任意指针。 要获得原始指针,必须将成员函数的地址移动到临时成员函数指针中,然后通过获取它的地址,然后取消引用它来传递。幸运的是,编译器会优化代码以去除多余的指针操作。
from Microsoft Detour library. They deal with code injection and discuss getting address of non-virual member functions. Of course it is compiler implementation specific stuff.
来自 Microsoft Detour 库。他们处理代码注入并讨论获取非虚拟成员函数的地址。当然,它是编译器实现特定的东西。
you can find the library here http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx
你可以在这里找到图书馆http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default.aspx
回答by Smartie
For anyone still looking for an answer of getting the memory address of the function (and not the jump), here is my solution:
对于仍在寻找获取函数的内存地址(而不是跳转)的答案的任何人,这是我的解决方案:
UINT32 RelativityToTrampoline = *(UINT32*)((UINT64)&Func + 1);
UINT64 RealFuncAddr = (UINT64)&Func + RelativityToTrampoline + 5;