1

在 C++ 中,我可以通过获取成员函数的地址轻松创建函数指针。但是,是否可以更改该本地函数的地址?

即说我在同一个类中有funcA() 和funcB(),定义不同。我希望将 funcA() 的地址更改为 funcB() 的地址,这样在运行时调用 funcA() 实际上会导致调用 funcB()。我知道这很丑陋,但我需要这样做,谢谢!

编辑 - - - - -

我正在尝试做的事情的背景:

我希望为现有代码库实现单元测试,我的所有模块都继承的基类中的一些方法是非虚拟的。我不允许编辑任何生产代码。我可以摆弄构建过程并在基类中替换相关方法设置为虚拟,但我认为我宁愿使用这样的 hack(我认为这是可能的)。

另外,出于技术上的好奇心,我对这个话题很感兴趣,因为通过尝试解决这个问题的过程,我学到了很多关于代码生成和函数查找等事情的底层工作原理,其中我刚读完大学二年级,还没有机会在学校学习。我不确定我是否会在学校里学到这样的东西,因为我在计算机工程专业而不是 CS 专业。

返回主题 funcA() 和 funcB() 方法确实具有相同的签名,所以问题是我只能使用 & 运算符获取函数的地址?我是否正确地说我不能更改函数的地址,或者在不破坏部分内存的情况下换出该地址的内容?如果将函数导出到 dll,那么 DLL 注入对于这种情况会是一种好方法吗?

4

7 回答 7

4

不会。函数被编译成可执行文件,并且它们的地址在程序的整个生命周期内都是固定的。

最接近的是虚函数。给我们一个你想要完成的例子,我保证有更好的方法。

于 2010-03-02T22:08:47.377 回答
1

它不能按照你描述的方式完成。更改静态绑定调用的目标的唯一方法是修改程序的实际可执行代码。C++ 语言没有可以做到这一点的功能。

如果您希望在运行时解析函数调用,则必须使用显式间接调用(通过函数指针调用),或使用基于运行时调用解析的语言特性(如虚函数),或者您可以使用平分枝与好老ifswitch。哪个更适合您的情况取决于您的具体问题。

于 2010-03-02T22:08:40.790 回答
1

从技术上讲,可以通过修改类型的 vtable 来实现虚函数,但如果不违反标准(导致未定义行为),您肯定无法做到这一点,并且需要了解您的特定编译器如何处理 vtables。

对于其他函数,这是不可能的,因为函数的地址是直接写入程序代码的,程序代码通常位于只读存储区。

于 2010-03-02T22:09:19.103 回答
0

我相当肯定这在纯 C++ 中是不可能的。C++ 不是动态语言。

于 2010-03-02T22:07:34.973 回答
0

你想要的是一个指向函数的指针,你可以将它指向 FuncA 或 FuncB 假设它们具有相同的签名。

于 2010-03-03T00:47:45.853 回答
0

你不能直接做你想做的事。但是,您可以使用一些您已经熟悉的东西——函数指针,通过一些稍微不同的标准来获得类似的结果。考虑:

// This type could be whatever you need, including a member function pointer type.
typedef void (*FunctionPointer)();

struct T {
   FunctionPointer Function;
};

现在您可以Function在任何给定T实例上设置成员,然后调用它。这大约是您可以合理获得的最接近的值,并且我认为由于您已经知道函数指针,因此您已经知道此解决方案。

您为什么不编辑您的问题,对您要解决的问题进行更完整的描述?就目前而言,听起来您确实在尝试做一些可怕的事情。

于 2010-03-03T01:02:45.340 回答
0

这很简单!

为了

在运行时调用 funcA() 实际上会导致调用 funcB()。

编写funcA()类似于以下内容:

int funcA( int a, int b) {
  return funcB( a, b );
}

:-)

于 2010-03-03T06:02:37.980 回答