c++ - 什么决定了调用 delete 时写入 C++ 指针的内容?

标签 c++ windows pointers memory-management

我有一个指向给定类的指针。比方说,指针是:

0x24083094

该指针指向:

0x03ac9184

这是我类(class)的虚函数表。这对我来说很有意义。在 windbg 中,一切看起来都是正确的。

我删除了上述指针。现在 0x24083094 是:

0x604751f8

但这不是一些随机垃圾,地址每次都放在那里,它始终是 0x604751f8!如此之多以至于我实际上可以使用该地址来确定该指针是否在我的应用程序执行之间被删除了!

但是为什么?它如何确定 0x604751f8 应该写在那里?

郑重声明,我使用的是 windows,在 visual studio 2003 下构建。

我知道我不能依赖于设置的值,即使它看起来是一致的,但我可以依赖它是不同的吗?即,如果指针被删除,0x03ac9184 将不会位于 0x24083094,对吧?放在那里的是什么?它可以是任何东西,但是 0x03ac9184 肯定不会在那里(否则我仍然可以调用方法,因为那是虚函数表)。我说得对吗?

我觉得我有答案了。删除后不能依赖任何东西。也许一些背景会帮助人们了解我来自哪里。本质上,我正在尝试修复一个指针从我下面被删除的错误。说来话长,我就不细说了。

基本上,我试图检测我是否处于这种情况,因此我可以优雅地退出我的函数。我想最简单和最好的方法就是弄清楚谁真正拥有这个指针,然后问他是否有任何改变。所以我将实现这样的修复。它避免了我正在讨论的任何 C++ delete hacker-y。

但是,有趣的是,在我们的代码中,我们有一个名为“BogusObject”的类,它本质上充当一个托盘,用于捕获不小心取消引用已释放对象的人。基本上,我们 Hook 我们自己的删除函数并将 BogusObject 类 bash 到任何已释放类的 vtable 中。

然后,如果有人调用他们,他们会收到一条好消息,意思是“嘿,伙计,出了点问题。”。这发生在我的情况下。即,0x604751f8+(someoffset) 在 BogusObject 类中。 但我们不再使用 BogusObject!它确实没有在任何地方设置(如果我完全删除 BogusObject 类,甚至可以正确链接),但我仍然最终收到了一条好消息,说出了点问题!但我现在认为这是巧合。

出于某种原因,运行时在删除该指针时将 0x604751f8 值放入该指针中,而这恰好对应于一个旨在捕获此类情况的类!

最佳答案

标准中的任何内容都不能决定那里写入的内容。 Visual Studio(至少在 Debug模式下)通常会在各处写入重要值,以帮助及早发现错误。

这个值不是你可以依赖的东西,但如果你发现这个值神秘地出现在你的程序中,你可以假设你在某个地方引用了已删除的内存。参见 this answer一个编译器下的值列表。

也完全有可能是一个空闲链表指针,指向下一 block 空闲内存。大多数内存分配器将它们的空闲内存保存在排序的链表中,使用它们正在跟踪的空闲内存来存储跟踪数据。

在任何情况下,您都不能将该指针值用于任何您想要继续工作的东西,除非您调用微软并获得一些文档说明为什么该值是现在的值,并让他们保证它不会改变.即使那样,也要知道您的代码现在与一个编译器的行为相关联。在 C++ 中,访问未分配的内存是未定义的和邪恶的。

编辑: 您甚至不能指望删除后该值会发生变化。没有什么说编译器需要修改删除时的数据。

关于c++ - 什么决定了调用 delete 时写入 C++ 指针的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/835922/

相关文章:

c - 为什么我无法在 C 中为我的结构创建新节点? (使用 Netbeans)

c - 在 C 中传递数组、指向 int 的指针

c++ - Moc'ed 文件神秘地从 Visual Studio 项目中排除

c++ - 将具有可变边界的二维数组传递给函数

c++ - strftime 性能与 snprintf

c - 为什么 memchr() 将 void 指针作为输入?

c++ - 哈希示例 - 多余的代码

java - 如何在批处理文件中检测 Activity 的 java 版本(32 位或 64 位)

node.js - ONBUILD 选项出错(Windows 中的 Docker 工具箱)

windows - CUDA 错误后重置 GPU 和驱动程序