【问题标题】:How to troubleshoot crashes in malloc如何解决 malloc 中的崩溃问题
【发布时间】:2011-09-20 05:45:10
【问题描述】:

我继承了大量遗留代码。到目前为止,它一直运行良好。突然在我无法在内部重现的客户试用中,它在 malloc 中崩溃。我认为我需要添加工具,例如在 malloc 之上我有自己的 malloc 来存储有关每个 malloc 的一些元信息,例如谁进行了 malloc 调用。当它崩溃时,我可以查找元信息并查看发生了什么。几年前我做过类似的事情,但现在想不起来了……我相信人们已经提出了更好的想法。很高兴有意见。

谢谢

【问题讨论】:

  • 有人正在破坏内存(“罪魁祸首”)。坠机现场只显示“受害者”。除了使用专用工具(valgrind 等)之外,您还可以尝试以下操作:检查崩溃站点周围的内存(假设您有核心文件和符号)。使用gdb,使用x/a <address、x/256wa $sp、x/s <address> 等检查内存。查找任何可识别的模式并将其与代码中其他地方的数据匹配。如果幸运的话,您将使用此类数据追溯到潜在的“罪魁祸首”。

标签: crash malloc


【解决方案1】:

内存分配是否中断?

试试valgrind。

Malloc 仍在崩溃。

好的,我将不得不假设您的意思是 SIGSEGV(分段错误)在 malloc 中触发。这通常是由堆损坏引起的。堆损坏本身不会导致分段错误,通常是数组访问超出数组边界的结果。这通常与您拨打malloc 的地点相去甚远。

malloc 在它返回给您的内存块“前面”存储一小段信息。该信息通常包含块的大小和指向下一个块的指针。不用说,更改其中任何一个都会导致问题。通常,下一个块指针被更改为无效地址,并且下次调用malloc 时,它最终会取消引用坏指针和分段错误。或者它没有并开始将随机内存解释为堆的一部分。最终它的运气用完了。

请注意,free 可能会发生同样的事情,如果正在释放的块或空闲块列表被弄乱了。

您如何捕获此类错误完全取决于您如何访问malloc 返回的内存。单个struct 的malloc 通常不是问题;它是malloc 的数组,通常会让你受益。使用负数(-1 或 -2)索引通常会给你当前块的块头,并且索引超过数组末尾可以给你下一个块的头。两者都是有效的内存位置,因此不会出现分段错误。

所以首先要尝试的是范围检查。您提到这出现在客户的网站上;可能是因为他们正在使用的数据集更大,或者输入数据已损坏(例如,它说要分配 100 个元素,然后初始化 101),或者他们正在以不同的顺序执行操作(这将错误隐藏在你的内部测试),或者做一些你没有测试过的事情。没有更多细节很难说。你应该考虑写一些东西来检查你的输入数据。

【讨论】:

  • Thanks.valgrind 没有捕捉到我们看到的错误。还有其他输入吗?
【解决方案2】:

试试阿桑

AddressSanitizer(又名 ASan)是用于 C/C++ 的内存错误检测器。它发现:

Use after free (dangling pointer dereference)
Heap buffer overflow
Stack buffer overflow
Global buffer overflow
Use after return
Use after scope
Initialization order bugs
Memory leaks

请找到链接以了解更多信息以及如何使用它

https://github.com/google/sanitizers/wiki/AddressSanitizer 和 https://github.com/google/sanitizers/wiki/AddressSanitizerFlags

【讨论】:

    【解决方案3】:

    我知道这是旧的,但只要我们有指针,这样的问题就会继续存在。尽管valgrind 是实现此目的的最佳工具,但它的学习曲线陡峭,而且结果常常令人生畏,无法理解。

    假设您正在开发一些 *nux,我可以建议的另一个工具是 electricfence。引用:

    Electric Fence 可帮助您检测两个常见的编程错误:

    software that overruns the boundaries of a malloc() memory allocation,
    software that touches a memory allocation that has been released by free().
    Unlike other malloc() debuggers, Electric Fence will detect read accesses
    as well as writes, and it will pinpoint the exact instruction that causes
    an error.
    

    使用非常简单。只需将您的代码与其他库链接lefence 当您运行应用程序时,内存损坏时会生成一个核心文件,而不是使用损坏的内存时。

    【讨论】:

      猜你喜欢
      • 2012-02-13
      • 2020-01-02
      • 2018-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多