2

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

我在地址上有一个 A 类的实例,比如说,0x0656a64c。然后当我查看变量时,它说它__vfptr指向0x077e7c0c

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

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

这可能是导致地址差异的原因吗?

这是VS调试器的截图

地址差异

4

2 回答 2

3

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

于 2017-11-09T09:40:29.160 回答
0

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

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

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

于 2021-05-21T15:53:34.343 回答