gpt4 book ai didi

c++ - 读取虚函数表(vtable)指针?

转载 作者:行者123 更新时间:2023-11-30 01:37:24 30 4
gpt4 key购买 nike

是否有明确定义的方法来访问类的虚表?在 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++ 选择这个模型的原因是因为这意味着当你为它分配一个 Derived 值时,Base 对象不会改变大小,明显的代价是丢失额外的信息。

最终效果是 C++ 对象在构造后不会更改类型。实际上,这意味着类型、和 vtable 可以由构造函数固定。赋值运算符不会碰它。

因此,通过在原始内存上调用赋值运算符,您会得到未定义的行为,特别是未初始化(垃圾)vtable。你不能指望它全为零。此外,在具有多重继承和虚拟继承的更复杂的情况下,还有其他数据字段可以找到各种子对象。那些也将是未初始化的。请注意,这些附加数据字段可能包含绝对指针。 memcpy 这样一个对象,您将指向原始对象的子对象。

你能检测到这个吗?不。由于原始内存中没有 CFoo 对象,您访问内存的所有尝试都是未定义行为。

解决方案是放置 new。这是将原始内存变成对象的魔法咒语。它可以使用任何构造函数,包括移动构造函数和复制构造函数,但(除了异常(exception))将为您留下一个有效的对象,具有适当的多态行为。

关于c++ - 读取虚函数表(vtable)指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49731821/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com