我有一个名为的 exe test.exe,通常用作独立应用程序。我想将此 exe 用作另一个应用程序 app.exe 中的模块(dll)。
test.exe 中的代码做了一些非常简单的事情,比如:
void doTest()
{
MyClass *inst = new MyClass();
inst->someMethod();
}
虚拟在哪里someMethod(),MyClass 有一个虚拟的 d'tor。
doTest()从 test.exe 导出,因此创建了一个名为 test.lib 的库 app.exe
与此库链接以在启动时静态加载 test.exe。
当我单独运行 test.exe 时,它运行得很好,但是当我从 app.exe 中加载它时,它会崩溃。
使用调试器单步执行代码会发现崩溃是在调用虚拟方法时发生的。事实证明,vftable 不知何故变坏了。
经过一番调查,事实证明,当 MyClass 的构造函数中的代码正在运行时,vftable 是一回事,但是当调用new返回时,它会被称为“本地 vftable”的其他东西替换。我发现这个关于为什么会这样的模糊讨论。
经过大约一天的调试后,我发现这个“本地 vftable”中的指针在两种情况下都是相同的,当 test.exe 是独立的和作为模块加载时。这不可能是正确的,因为 test.exe 被加载到不同的地址......
为了测试这个理论,我将链接器选项中的加载地址更改为 test.exe 在 app.exe 中时加载的地址,现在,瞧,一切正常。
显然,这不是一个永久的解决方案,因为下一次这个随机选择的地址可能会被占用,同样的问题会再次出现。
所以我的问题是:为什么这个“本地 vftable”与 exe 的静态加载地址相关联?将exe作为模块加载是一件坏事吗?为什么exe假定它已加载到其静态地址?
只是为了上下文:这一切都是通过 MSVC 2008、Windows XP x64 完成的。