我有一个名为的 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 完成的。