获取成员函数的内存地址?

问题描述 投票:0回答:4

如何获取 C++ 中成员函数的绝对地址? (我需要这个来敲击。)

成员函数指针不起作用,因为我无法将它们转换为绝对地址(

void *
)——我需要知道内存中实际函数的地址,而不仅仅是相对于类型的地址。

c++ visual-c++ memory-address member-functions
4个回答
40
投票

MSVC 中存在一种获取成员函数地址的语法(恕我直言,从 MSVC 2005 开始)。但这非常棘手。而且,获得的指针不可能通过常规手段转换为其他指针类型。尽管有一种方法可以做到这一点。

示例如下:

// 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

事实上,即使有

reinterpret_cast
,传统的演员阵容也不起作用,这可能意味着MS不会强烈推荐这种演员阵容。

尽管如此,您可以这样做。当然,这完全取决于实现,您必须知道适当的调用约定来进行 thunking + 具有适当的汇编技能。


7
投票

试试这个。应该让你将任何东西投射到任何东西:)

template<typename OUT, typename IN>
OUT ForceCast( IN in )
{
    union
    {
        IN  in;
        OUT out;
    }
    u = { in };

    return u.out;
};

然后

void* member_address = ForceCast<void*>(&SomeClass::SomeMethod);

5
投票

默认情况下,C++ 成员函数使用 __thiscall 调用 习俗。为了绕行成员函数,蹦床 并且绕行必须具有与 目标函数。不幸的是,VC编译器不支持 __thiscall,因此创建合法的绕行和蹦床函数的唯一方法是使它们成为“绕行”类的类成员。

另外,C++不支持将指针转换为成员 函数指向任意指针。 要获取原始指针,地址 成员函数的必须移动到临时成员函数中 指针,然后通过获取它的地址来传递,然后取消引用它。 幸运的是,编译器会优化代码,删除多余的 指针操作。

来自 Microsoft Detour 库。他们处理代码注入并讨论获取非虚拟成员函数的地址。当然,这是编译器实现特定的东西。

您可以在这里找到该库https://web.archive.org/web/20111228203836/http://research.microsoft.com/en-us/downloads/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/default。 ASPX


2
投票

对于任何仍在寻找获取函数内存地址(而不是跳转)答案的人,这是我的解决方案:

UINT32 RelativityToTrampoline = *(UINT32*)((UINT64)&Func + 1);
UINT64 RealFuncAddr = (UINT64)&Func + RelativityToTrampoline + 5;
© www.soinside.com 2019 - 2024. All rights reserved.