【问题标题】:How can I debug 'zend_mm_heap corrupted' for my php extension如何为我的 php 扩展调试“zend_mm_heap 损坏”
【发布时间】:2014-06-20 02:23:25
【问题描述】:

问题

我编写了一个 php 扩展程序(PHP 5.3),对于简单的测试似乎可以正常工作,但是当我开始多次调用它时,我开始看到错误:

zend_mm_heap 损坏

通常通过控制台或apache错误日志,我有时也会看到错误

[Thu Jun 19 16:12:31.934289 2014] [:error] [pid 560] [client 127.0.0.1:35410] PHP 致命错误:允许的内存大小为 134217728 字节已用尽(尝试分配 139678164955264 字节)未知在第 0 行

我尝试过的事情

我已经尝试找到问题发生的确切位置,但它似乎发生在为调用扩展的我的 php 类调用析构函数之间但在构造函数运行构造函数的第一行之前(注意,我主要使用 phpunit 来诊断这个问题,如果我在浏览器中运行它,它通常会工作一次,然后在下一次尝试时将错误抛出到日志中,并在我的浏览器窗口中显示“连接已重置”,因此没有输出。

我尝试使用 memory_get_usage 添加调试行并安装扩展 memprof,但所有输出均未显示任何严重的内存问题,而且我从未见过超过 8mb 的内存使用量。

我查看了其他关于更改 php 设置以处理 zend_mm_corrupted 问题的堆栈溢出帖子,禁用/启用垃圾收集但没有任何程度的成功。

我在寻找什么

我意识到这里没有足够的信息来可能知道是什么导致我认为是内存泄漏,所以我想知道我的问题有哪些可能和可能的原因以及我该如何进行诊断这个issue来查找问题出在哪里。

注意:

我尝试使用 --enable-debug 构建我的扩展,但它作为无法识别的参数出现。

编辑:Valgrind

我用 valgrind 运行过它并得到以下输出:

--24803-- REDIR:0x4ebde30 (__GI_strncmp) 重定向到 0x4c2dd20 (__GI_strncmp)
--24803-- REDIR: 0x4ec1820 (__GI_stpcpy) 重定向到 0x4c2f860 (__GI_stpcpy)
分段错误(核心转储)
==24803==
==24803== 堆摘要:
==24803== 在退出时使用:72 个块中的 2,401 个字节
==24803== 总堆使用量:73 个分配,1 个释放,2,417 个字节分配
==24803==
==24803== 搜索指向 72 个未释放块的指针
==24803== 已检查 92,624 个字节
==24803==
==24803== 泄漏摘要:
==24803== 肯定丢失:0 个块中的 0 个字节
==24803== 间接丢失:0 个块中的 0 个字节
==24803== 可能丢失:0 个块中的 0 个字节
==24803== 仍然可以访问:72 个块中的 2,401 个字节
==24803== 抑制:0 个块中的 0 个字节
==24803== 未显示可到达块(找到指针的块)。
==24803== 要查看它们,请使用以下命令重新运行:--leak-check=full --show-reachable=yes
==24803==
==24803== 错误摘要:0 个上下文中的 0 个错误(已抑制:2 个中的 2 个)
--24803--
--24803-- used_suppression: 2 dl-hack3-cond-1
==24803==
==24803== 错误摘要:0 个上下文中的 0 个错误(抑制:2 个中的 2 个)

这向我表明,问题可能不是内存泄漏,但对此不确定。

【问题讨论】:

    标签: c memory-management memory-leaks php-extension


    【解决方案1】:

    在我看来,您的程序确实存在堆内存损坏。通过查看您的代码 sn-p 或错误的调用堆栈,这有点难以找到。您可能希望在一些动态工具(Valgrind、WindDBG/Pageheap)下运行您的程序以跟踪实际的错误来源。

    $ valgrind --tool=memcheck --db-attach=yes ./a.out

    这样,当您检测到第一个内存错误时,Valgrind 会将您的程序附加到调试器中,以便您可以进行实时调试(GDB)。这应该是了解和解决您的问题的最佳方式。

    允许的内存大小为 134217728 字节已用尽(试图分配 139678164955264 字节)在第 0 行的未知中

    您的程序中的某个地方似乎正在执行有符号到无符号的转换。通常分配器具有无符号类型的大小参数,因此它将负值解释为非常大的类型,在这种情况下,分配会失败。

    【讨论】:

      猜你喜欢
      • 2017-08-20
      • 2012-02-17
      • 1970-01-01
      • 2016-01-28
      • 2016-01-15
      • 2018-11-19
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      相关资源
      最近更新 更多