【问题标题】:How to detect double deletes or deletes on unallocated memory in C++?如何检测 C++ 中未分配内存的双重删除或删除?
【发布时间】:2011-09-13 16:50:54
【问题描述】:

我正在编写全局删除/新操作符的调试版本,以检测内存泄漏、双重删除和未分配内存上的删除。

就“new”运算符而言,我覆盖了全局 new 运算符并使用宏传递了文件名和行号信息。重写的“new”操作符将内存地址、文件名、大小和行号信息存储在以地址为键的映射中。

我也覆盖了“删除”运算符,它从地图中删除了已删除地址的条目。现在我想将删除的内存信息存储在另一个映射中,该映射存储调用“删除”的文件名和行号信息。

但删除操作符只接受参数(要删除的对象的内存地址)。 有人可以告诉如何检测代码中的双重删除吗?

【问题讨论】:

  • 我认为有这方面的工具。
  • 为什么不能表现得像“new”一样,即删除时,检查传入的地址,如果它已经在“deleted”映射中,那就是双重删除。问题出在哪里?
  • 您可能还需要考虑使用模式(如 0xbaadf00d)写入已分配/解除分配的内存,以查看是否访问了已解除分配或未初始化的内存。 Visual Studio 调试堆可以做到这一点,还有更多。见stackoverflow.com/questions/127386/…
  • @FredOverflow:感谢您将我指向那里,但即使在那里,程序也会检测到双重删除(甚至可能是未分配内存上的删除)。我很想知道在双重删除的内存上第一次删除是从哪里调用的。在大型代码库中,这是一个有用的信息。

标签: c++ memory memory-leaks new-operator delete-operator


【解决方案1】:

您已经在重载的new 中创建了分配的内存地址(键)和文件名、行号(值字段)的映射。

在重载删除时,只需检查所传递的地址是否存在于您创建的地图中。

如果是,您认为对delete 的调用是有效的,并从您的地图中删除该地址条目。

如果否,则认为删除调用是错误的,delete called on a pointer not allocated through your newtrying to call delete multiple times

【讨论】:

  • 严格来说,你需要保护地图不被不同线程同时访问。
  • @Eric:说得对,很好,虽然我相信 OP 一定已经考虑到了这一点,作为他/她的设计的一部分。
  • 我想检查是否发生双重删除,首先删除该内存地址的文件和行号。
  • @Eric: 是的,我会保护读/写映射到线程安全。
【解决方案2】:

如果您需要区分双重删除和从未分配内存的删除,只需将地址映射到已分配内存的 state,而不是从映射中删除元素,只需更新state 将其标记为已经发布。每次删除中的测试将验证地址是否存在(如果不存在,则错误正在删除从未分配的地址),如果存在,则内存是否已被释放(如果已释放,则错误为双重释放)。

【讨论】:

  • 好主意,更新一张地图比维护两张要好。但是如何检查第一次删除是从哪里调用的呢?
  • @nikhil kohli:您真的应该使用预打包的解决方案(考虑在 linux 中使用 valgrind)。但基本上,地图必须存储更多信息。关键仍然是地址,但内容必须存储您需要的附加信息(内存是从哪里分配的——以防它泄漏——它是从哪里释放的——检测双重删除......)
【解决方案3】:

有两个不同的问题:检测双重删除(相反 删除从未分配的内存,并确定在哪里 它发生的程序。 首先,我的调试operator new 之前分配了警戒区 并在它返回块之后(也用于检测过去的写入 以解除分配结束);我在operator delete 中将它们设置为不同的模式,并检查此模式。总有这样的机会 从未分配的内存可能包含这种模式,但机会是 非常非常小。 确定代码中发生错误的位置更加困难。 我编写了执行堆栈回溯的代码,但它非常系统 依赖。 (我有适用于 Sparc 上的 Solaris、Intel 上的 Linux 和 Windows。)它报告的只是十六进制的返回地址;取决于 程序员使用其他工具来分析这些。 GNU binutils package有一个程序addr2line,在Linux下运行良好,但是 给定一个排序的地图,手动操作并不难。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    相关资源
    最近更新 更多