c++ - 如何使用动态转换检测到指针的删除

标签 c++ vtable dynamic-cast

如图here ,可以使用 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;  

}

输出:

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

说明检测到vtable被删除。

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

该解决方案是否完全可移植?

谢谢

最佳答案

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

观察到的行为的原因很简单,一个对象在销毁过程中改变了类型:从一个具体类型的对象开始,它改变了层次结构中的所有类型。在每个点上,虚函数都会发生变化,并且 vtable(或类似的)会被替换。 dynamic_cast<...>()简单地检测存储在对象位置的字节的这种变化。

如果您想证明此技术不能可靠地工作,您可以将已删除内存的内容设置为随机位模式或派生类型最多的对象的位模式:随机位模式可能会导致崩溃和 memcpy()可能声称该对象是静物。当然,因为它是未定义的行为,所以任何事情都有可能发生。

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

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:

  • ...
  • the pointer is used as the operand of a dynamic_cast (5.2.7). ...

奇怪的是,dynamic_cast 上最后一个项目符号中的示例不使用 dynamic_cast .

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

关于c++ - 如何使用动态转换检测到指针的删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24113066/

相关文章:

c++ - Windows 上的 std::basic_string<TCHAR> 会优于 std::wstring 吗?

c++ - Qt 链接器错误 : "undefined reference to vtable"

c++ - C++ 中的对象内存布局及其结构如何依赖于大多数平台

c++ - dynamic_cast 解决实现困境

C++ bad_cast 异常将 *this 转换为派生模板类

C++访问抽象类指针 vector 子类的成员

c++ - mingw:从 lambda 到函数指针的无效转换

c++ - 编译错误 Undefined symbols for architecture x86_64 :

c++ - 返回虚函数的静态成员,缺少抽象类的 vtable

c++ - 这是对 dynamic_cast 的正确使用吗?