问题

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


  zend_mm_heap损坏


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


  [2014年6月19日,星期四,16:12:31.934289] [:错误] [pid 560] [客户端127.0.0.1:35410] PHP致命错误:第0行上的“未知”中的134217728字节已用完(允许分配139678164955264字节)允许的内存大小


我试图做的

我试过找出问题发生的确切地点,但它似乎发生在为我的php类调用扩展程序的析构函数之间,但在构造函数运行构造函数的第一行之前(注意,我主要使用phpunit来诊断一下,如果我在浏览器中运行它,通常它将运行一次,然后在下次尝试中在浏览器窗口中显示“连接已重置”,从而将错误抛出日志。

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

我已经查看了其他有关更改php设置以解决zend_mm_corrupted问题,禁用/启用垃圾收集而没有任何成功的堆栈溢出文章。

我在寻找什么

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

注意:

我曾尝试使用--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个)


这向我表明,也许问题不是内存泄漏,但不确定。

最佳答案

在我看来,您的程序确实存在堆内存损坏。通过查找您的代码片段或错误的调用堆栈,很难找到这个位置。您可能希望在某些动态工具(Valgrind,WindDBG / Pageheap)下运行程序以跟踪实际的错误源。


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


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


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


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

09-07 02:48