所以,我正在玩Visual Studio的测试套件,我发现了一些有趣的东西:
我在地址上有一个A类实例,比如0x0656a64c
。
然后,当我查看变量时,它表示其__vfptr
指向0x077e7c0c
。
据我所知,一个班级'虚拟表指针应该位于类实例的前4个字节(或64位应用程序中的8个字节),除非它是多重继承的情况(然后它只是第一个vtable地址的偏移量) )。
我发现Visual Studio将我的测试编译成.dll并运行其动态加载.dll的测试工具。
这可能导致地址差异吗?
这是VS调试器的屏幕截图
答案 0 :(得分:3)
您混淆了vptr的地址以及vptr指向的地址。 (大致)正确的是,通常的实现是vptr是对象中的第一件事 - 但Visual Studio向您显示 vtable 的地址(在类的所有对象之间共享) )。
答案 1 :(得分:0)
这只是 MS C++ 编译器的正常行为。 2 创建相同类对象实例的 DLL 将具有不同的 vtable。直觉会说 vtable 应该与所有实例共享,而不管 DLL 的代码创建(新)它。类的实现应该是通用的。不是真的。
动态释放 DLL 时会产生危险。分配的所有对象可能仍处于有效(进程)堆中。但是,如果它有一个虚拟析构函数,那么它是在 vtable 中定义的。它现在处于空闲空间。因此 vtable 已损坏。任何使用它都会产生异常。
解决方案是在释放 DLL 之前清除动态 DLL 进行的任何/所有分配,这些分配可能也具有 vtable(例如虚拟析构函数)。在进程堆中进行的任何不指向基于 DLL 的 vtable 的分配都可以。如果没有正确跟踪,最坏的情况是内存泄漏。