如何使用动态强制转换检测到指针的删除

tak*_*004 8 c++ dynamic-cast vtable

如图所示在这里,人们可以使用dynamic_cast来检测已删除的指针:

#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;  

}
Run Code Online (Sandbox Code Playgroud)

输出:

dynamic_cast<B*>( pB) worked
dynamic_cast<B*>( (A*)pB) worked
dynamic_cast<B*>( pB) worked
dynamic_cast<B*>( (A*)pB) failed
Run Code Online (Sandbox Code Playgroud)

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

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

那个解决方案完全可移植吗?

谢谢

Die*_*ühl 6

首先,尝试以任何形式使用已删除的对象会导致未定义的行为:无论您看到什么结果都可能发生!

观察到行为的原因很简单,一个对象在破坏期间改变了类型:从作为具体类型的对象,它改变了层次结构中的所有类型.在每个点,虚函数都会改变,vtable(或类似的)会被替换.在dynamic_cast<...>()简单地检测在所述对象的位置strored字节这种变化.

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

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

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

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

奇怪的是,最后一个子弹上的例子dynamic_cast没有使用dynamic_cast.

当然,该对象也可能被释放,在这种情况下,上述保证甚至不适用.