【问题标题】:can memory corruption be caused by invalid *reading* freed memory?无效的*读取*释放的内存会导致内存损坏吗?
【发布时间】:2010-07-03 18:15:18
【问题描述】:

我来了

*** 检测到 glibc *** (/my/program/...): malloc(): 内存损坏: 0xf28000fa ***

我在 valgrind 下运行,它报告了已释放的读取内存的情况,但没有写入非法内存的情况。

读取释放的内存会导致内存损坏吗?如果没有,还有什么建议可以超越 valgrind 输出?

【问题讨论】:

    标签: c++ linux malloc valgrind glibc


    【解决方案1】:

    您可以使用 GDB 来监视此内存地址中的每次写入,如下所示:

    (gdb) watch *((int*)0xf28000fa)
    

    然后就可以调试问题出在哪里了。

    读取不会导致内存损坏,但在很多情况下你甚至无法想象这可能是造成这种情况的原因,而 Valgrind 并不是一个完美的工具。

    查看更多关于调试内存问题的信息here

    【讨论】:

      【解决方案2】:

      它不会破坏您读取的内存,但不会对您的程序的工作产生奇迹。

      【讨论】:

        【解决方案3】:

        读取释放的内存也被认为是内存损坏。

        您也可以查看http://en.wikipedia.org/wiki/Memory_corruption

        【讨论】:

          【解决方案4】:

          不,读取无效位置不可能导致您看到的错误。如果该位置在您的地址空间中有效,那么您将只是在阅读垃圾邮件,否则,您将遇到分段错误。

          检查 valgrind 的输出以查看无效读取的来源 - 这将为您提供真正错误所在的提示。一旦你找到这个,我很确定真正的罪魁祸首不会很远,而且很可能是无效写入。

          【讨论】:

          • 但是如果有一个无效的写入,为什么 valgrind 不显示呢?
          • 这是我不知道答案的问题,但是您是否查看过导致无效读取的原因?
          • @steve: 一种可能性是非法读取导致某些代码使用不是invalid的地址,在受valgrind保护的意义上,但是错误,因为它不是代码应该使用的地址。这反过来可能导致将不一致检测为内存损坏。损坏并不一定意味着发生了可检测到的无效写入,只是某些数据结构不一致。作为一个简单的假设示例,假设将一个列表节点添加到列表中两次 - 您永远不会执行非法写入,但您会得到一个损坏的列表。
          【解决方案5】:

          这在当前处理器上应该不常见,但我曾在甚至读取操作都可以发挥作用的平台上工作。在特定的 6502 处理器中映射了 I/O,因此具有 I/O 映射地址的常规“读取”指令可以做一些令人惊讶的事情。

          大约 30 年前,我被它所困扰,因为我的错误读取引发了内存库切换(即内存的每个字节,包括包含代码的区域,在该指令之后都获得了一个新的不同值)。 有趣的是,它并不是真正的“无意”错误阅读……即使我知道这将是垃圾,我也确实阅读了,因为这为我节省了一些汇编指令……这不是一个聪明的举动。

          【讨论】:

            【解决方案6】:

            真正会发生的是,free 可以使用 madvise(MADV_DONTNEED) 系统调用告诉内核“我不需要这个页面,删除它”(参见 madvise(2) 手册页)。如果该页面真的被释放并且您从中读取任何内容,内核将默默地提供全新的页面,将其归零 - 从而导致您的应用程序遇到完全意外的数据!

            【讨论】:

              猜你喜欢
              • 2016-11-06
              • 1970-01-01
              • 2014-01-07
              • 2011-08-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-02-09
              相关资源
              最近更新 更多