正在读取虚拟函数表 (vtable) 指针?
Reading the virtual function table (vtable) pointer?
有没有一种定义明确的方法来访问类的vtable?在Visual Studio中调试时,我可以扩展"this",例如:this->_ptr->__vfptr。但是此路径似乎无法从代码中获得。
我需要它来对自定义堆实现(嵌入式环境)进行单元测试。
背景
我们有一个错误,在我们的自定义堆上分配的对象(只不过是一个特定大小的数组)按预期工作,直到我们想添加一个具有虚拟函数的对象(我们花了相当长的时间才意识到这种添加是问题的原因)。我们犯的错误是将一个对象分配给内存,在分配之前没有初始化任何对象。我们在编写该代码时没有太注意,并且由于它与其他所有内容一起使用并经过测试,我们认为它可以工作。下面是一些示例代码:
int array_ptr[sizeof(SomeObject)];
*((SomeObject*) array_ptr) = SomeObject(); // Does only partially initialize the object!
一旦我们意识到这条线是问题所在,也很清楚为什么会这样。
啊哈,我现在明白了,评论中的澄清。
您正在仅具有CFoo
大小的原始内存上调用CFoo::operator=
。这确实不会在常见的实现上设置一个vtable。这特定于C++中的分配的工作方式。C++中的对象分配定义为切片。如果将Derived
对象分配给Base
类,则会调用Base::operator=(Base const& src)
.这仅复制Derived
对象的 Base 子对象。
C++选择此模型的原因是,这意味着当您为Base
对象分配Derived
值时,它的大小不会改变,代价是丢失额外的信息。
净效果是C++对象在构造后不会改变类型。实际上,这意味着类型和vtable可以由构造函数修复。赋值运算符不会触摸它。
因此,通过在原始内存上调用赋值运算符,您将获得未定义的行为,特别是未初始化的(垃圾)vtable。你不能指望它都是零。此外,在具有多重和虚拟继承的更复杂的情况下,还有其他数据字段来查找各种子对象。这些也将是未初始化的。请注意,这些附加数据字段可能包含绝对指针。memcpy
这样的对象,您将指向原始对象的子对象。
你能察觉到这一点吗?不。您访问内存的所有尝试都是未定义的行为,因为原始内存中没有CFoo
对象。
解决方案是放置new
。这是将原始记忆变成物体的神奇咒语。它可以使用任何构造函数,包括移动构造函数和复制构造函数,但(除非例外)将为你留下一个有效的对象,具有适当的多态行为。
好的,所以从上面的 MSalters 和其他评论者那里学习,我知道没有直接的方法来阅读 vtable 指针。但是,我想出了一个足以满足我需求的解决方案(即测试 vtable 指针是否正确初始化)。所以这是代码(请注意,我假设我得到的是 vtable 指针 sizeof(size_t) == sizeof(EmptyClassWithOneVirtualFunction)):
class EmptyClassWithOneVirtualFunction
{
virtual void testFunction() {}
};
void test_staticNew_object_vtable()
{
EmptyClassWithOneVirtualFunction correctObject;
EmptyClassWithOneVirtualFunction* object = mem::static_new<EmptyClassWithOneVirtualFunction>();
size_t* correctObjectVtablePtr = ( (size_t*) &correctObject );
size_t* objectVtablePtr = ( (size_t*) object );
TS_ASSERT_EQUALS( *objectVtablePtr, *correctObjectVtablePtr );
}
应该指出的是,这是在调试模式下构建的测试代码,没有优化。对我来说,即使以这种不完全"安全"的方式也能捕获此错误,比仅仅因为没有正确的方法而跳过它更有价值。
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 为什么重复的空基存储不与 vtable 指针重叠?
- 为什么 fdump-class-hierarchy 为虚函数提供了两个指针 int vtable
- 正在读取虚拟函数表 (vtable) 指针?
- C vtable在多个继承中,指向thunk方法的指针
- 我明白为什么,但是虚拟函数/VTable 究竟如何允许通过指针访问正确的函数?
- 从C 中的VTable获取方法指针
- 将VTable类铸造为void指针(C )
- 从派生的指针中调用虚拟功能,而无需支付VTable价格
- c++:vtable是否包含指向非虚拟函数的指针
- 我实际上是在调用 ctor 并在指向对象的指针上初始化 vtable 吗?C++
- 从 Objdump 实用程序检索 vptr(指向虚拟表又名 VTABLE 的指针)
- 指向 D3D11 设备 vtable 的正确指针
- 指向不同地址的 vTable 和函数指针
- 如果类实现多个接口,VTable 的方法指针顺序是什么?
- 在VTable指针和malloc