加载 .dll 时实例指针与 vfptr 不同

Instance pointer differs from vfptr when .dll is loaded

所以,我在玩 Visual Studio 的测试套件时发现了一些有趣的东西:

我有一个 class A 的实例,地址是 0x0656a64c。 然后当我查看变量时,它说它的 __vfptr 指向 0x077e7c0c.

据我所知,class' 虚拟 table 指针应该位于 class 的前 4 个字节(或 64 位应用程序中的 8 个字节)例如,除非是多重继承的情况(那么它只是第一个 vtable 地址的偏移量)。

我观察到 Visual Studio 将我的测试编译成 .dll 并且 运行 它的测试工具动态加载了 .dll。

这可能是造成地址差异的原因吗?

这是 VS 调试器的屏幕截图

您混淆了 vptr 的地址和 vptr 指向的地址。你(大致)是正确的,通常的实现是 vptr 是对象中的第一件事 - 但 Visual Studio 向你显示 vtable 的地址(这是共享的class).

的所有对象之间

这只是 MS C++ 编译器的正常行为。 2 个创建相同 class 对象实例的 DLL 将具有不同的 vtable。直觉会说 vtable 应该与所有实例共享,而不管创建(新)它的 DLL 代码是什么。应该是共同执行的class。不正确。

这会在动态释放 DLL 时产生危险。分配的所有对象可能仍在有效(进程)堆中。但是,如果它有一个虚拟析构函数,那么它是在 vtable 中定义的。现在已释放 space。因此 vtable 已损坏。任何使用它都会产生异常。

解决方案是在释放 DLL 之前清理 any/all 动态 DLL 进行的分配,这些动态 DLL 可能也有一个 vtable(例如虚拟析构函数)。在进程堆中进行的任何不指向基于 DLL 的 vtable 的分配都可以。如果没有正确跟踪,最坏的情况是内存泄漏。