如何删除使用动态转换检测的指针 [英] How is the deletion of a pointer detected using dynamic cast

查看:101
本文介绍了如何删除使用动态转换检测的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里所示,您可以使用 dynamic_cast 检测已删除的指针:

As shown here, one can use dynamic_cast to detect a deleted pointer:

#include <iostream>

using namespace std;

class A
{
public:
   A() {}
   virtual ~A() {}
};

class B : public A
{
public:
   B() {}
};

int main()
{
   B* pB =  new B;

   cout << "dynamic_cast<B*>( pB) ";
   cout << ( dynamic_cast<B*>(pB) ? "worked" : "failed") << endl;  

   cout << "dynamic_cast<B*>( (A*)pB) ";
   cout << ( dynamic_cast<B*>( (A*)pB) ? "worked" : "failed") << endl;  

   delete pB; 

   cout << "dynamic_cast<B*>( pB) ";
   cout << ( dynamic_cast<B*>(pB) ? "worked" : "failed") << endl;  

   cout << "dynamic_cast<B*>( (A*)pB) ";
   cout << ( dynamic_cast<B*>( (A*)pB) ? "worked" : "failed") << endl;  

}

输出:

dynamic_cast<B*>( pB) worked
dynamic_cast<B*>( (A*)pB) worked
dynamic_cast<B*>( pB) worked
dynamic_cast<B*>( (A*)pB) failed

它解释了检测到vtable的删除。

It explains that the deletion of the vtable is detected.

但我想知道这是怎么可能的,因为我们不覆盖释放的内存?

But I am wondering how is that possible since we do not overwrite the freed memory?

解决方案完全可移植?

感谢

推荐答案

使用任何形式的删除对象会导致未定义的行为:无论你看到什么结果都可能发生!

First off, trying to use a deleted object in any form results in undefined behavior: whatever result you see could happen!

观察到的行为的原因只是一个对象在销毁期间更改类型:从作为具体类型的对象,它改变通过层次结构中的所有类型。在每个点,虚拟函数改变,并且vtable(或类似的)被替换。 dynamic_cast< ...>()只是检测对象位置处的已更改字节中的此更改。

The reason of the observed behavior is simply that an object changes type during destruction: from being an object of the concrete type it change through all of the types in the hierarchy. At each point the virtual functions change and the vtable (or similar) gets replaced. The dynamic_cast<...>() simply detects this change in the bytes strored at the location of the object.

如果您想要显示此技术不可靠地工作,您可以将删除的内存的内容设置为随机位模式或最大派生类型的对象的位模式:随机位模式可能会产生崩溃,并且 memcpy()可能声称对象仍然是生命。当然,因为它是未定义的行为,任何事情都可能发生。

In case you feel like wanting to show that this technique doesn't reliably work you can just set the content of deleted memory to a random bit pattern or the bit pattern of an object of the most derived type: a random bit pattern probably yields a crash and memcpy() probably claims that the object is still life. Of course, since it is undefined behavior anything can happen.

这个3.8 [basic.life]段落5的一个相关部分:

One relevant section on this 3.8 [basic.life] paragraph 5:


在对象的生命周期开始之前,但在对象将占用的存储已经被分配之后,或者在对象的生命周期结束之后,在对象的存储之前占用被重新使用或释放​​,则可以使用指向对象将被或将被定位的存储位置的任何指针,但是仅以有限的方式。对于正在建设或销毁的对象,见12.7。否则,这样的指针指向分配的存储(3.7.4.2),并且使用指针,就好像指针是 void * 的类型,
是明确定义的。允许通过这种指针的间接,但是所得到的左值仅可以以有限的方式使用,如下所述。如果出现以下情况,程序具有未定义的行为:

Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a pointer refers to allocated storage (3.7.4.2), and using the pointer as if the pointer were of type void*, is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The program has undefined behavior if:


  • ...

  • 指针用作操作数的dynamic_cast(5.2.7)。 ...

奇怪的是, 不使用 dynamic_cast

当然,在这种情况下,上述保证甚至不适用。

Of course, the object is also probably released in which case the above guarantees don't even apply.

这篇关于如何删除使用动态转换检测的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆