“zend_mm_heap corrupted”是什么意思

时间:2010-02-11 21:49:53

标签: php heap fedora php-internals

突然之间,我的应用程序出现了问题,这是我以前从未遇到的问题。我决定检查Apache的错误日志,我发现一条错误消息“zend_mm_heap corrupted”。这是什么意思。

操作系统:Fedora Core 8 Apache:2.2.9 PHP:5.2.6

40 个答案:

答案 0 :(得分:51)

经过多次试验和错误,我发现如果我增加php.ini文件中的output_buffering值,则此错误消失

答案 1 :(得分:45)

我在PHP 5.5下遇到同样的错误,并且增加输出缓冲没有帮助。我没有运行APC,所以这不是问题。我终于将它追溯到 opcache ,我只需要从cli中禁用它。有一个特定的设置:

opcache.enable_cli=0

切换后,zend_mm_heap损坏的错误就消失了。

答案 2 :(得分:42)

如果你在Linux机器上,请在命令行上试试

export USE_ZEND_ALLOC=0

答案 3 :(得分:38)

这不是通过更改配置选项必须解决的问题。

更改配置选项有时会产生积极影响,但它可以轻易地使事情变得更糟,或者根本不做任何事情。

错误的本质是:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void) {
    void **mem = malloc(sizeof(char)*3);
    void *ptr;

    /* read past end */
    ptr = (char*) mem[5];   

    /* write past end */
    memcpy(mem[5], "whatever", sizeof("whatever"));

    /* free invalid pointer */
    free((void*) mem[3]);

    return 0;
}

上面的代码可以编译为:

gcc -g -o corrupt corrupt.c

使用valgrind执行代码,您可以看到许多内存错误,最终导致分段错误:

krakjoe@fiji:/usr/src/php-src$ valgrind ./corrupt
==9749== Memcheck, a memory error detector
==9749== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==9749== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==9749== Command: ./corrupt
==9749== 
==9749== Invalid read of size 8
==9749==    at 0x4005F7: main (an.c:10)
==9749==  Address 0x51fc068 is 24 bytes after a block of size 16 in arena "client"
==9749== 
==9749== Invalid read of size 8
==9749==    at 0x400607: main (an.c:13)
==9749==  Address 0x51fc068 is 24 bytes after a block of size 16 in arena "client"
==9749== 
==9749== Invalid write of size 2
==9749==    at 0x4C2F7E3: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9749==    by 0x40061B: main (an.c:13)
==9749==  Address 0x50 is not stack'd, malloc'd or (recently) free'd
==9749== 
==9749== 
==9749== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==9749==  Access not within mapped region at address 0x50
==9749==    at 0x4C2F7E3: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9749==    by 0x40061B: main (an.c:13)
==9749==  If you believe this happened as a result of a stack
==9749==  overflow in your program's main thread (unlikely but
==9749==  possible), you can try to increase the size of the
==9749==  main thread stack using the --main-stacksize= flag.
==9749==  The main thread stack size used in this run was 8388608.
==9749== 
==9749== HEAP SUMMARY:
==9749==     in use at exit: 3 bytes in 1 blocks
==9749==   total heap usage: 1 allocs, 0 frees, 3 bytes allocated
==9749== 
==9749== LEAK SUMMARY:
==9749==    definitely lost: 0 bytes in 0 blocks
==9749==    indirectly lost: 0 bytes in 0 blocks
==9749==      possibly lost: 0 bytes in 0 blocks
==9749==    still reachable: 3 bytes in 1 blocks
==9749==         suppressed: 0 bytes in 0 blocks
==9749== Rerun with --leak-check=full to see details of leaked memory
==9749== 
==9749== For counts of detected and suppressed errors, rerun with: -v
==9749== ERROR SUMMARY: 4 errors from 3 contexts (suppressed: 0 from 0)
Segmentation fault

如果你不知道,你已经发现mem是堆分配的内存;堆指的是程序在运行时可用的内存区域,因为程序显式请求它(在我们的例子中使用malloc)。

如果您使用可怕的代码,您会发现并非所有明显不正确的语句都会导致分段错误(致命的终止错误)。

我在示例代码中明确地提出了这些错误,但是在内存管理环境中很容易发生同样的错误:如果某些代码没有维护变量(或其他符号)的引用计数正确的方法,例如,如果它过早自由,另一段代码可能从已经自由的内存中读取,如果它以某种方式存储地址错误,另一段代码可能写入无效内存,它可能是免费的两次......

这些不是可以在PHP中调试的问题,它们绝对需要内部开发人员的注意。

行动方针应该是:

  1. http://bugs.php.net上打开错误报告
    • 如果您遇到段错误,请尝试提供backtrace
    • 包括尽可能多的配置信息,特别是如果您使用opcache包括优化级别。
    • 继续检查错误报告以获取更新,可能会要求提供更多信息。
  2. 如果加载了opcache,请禁用优化
    • 我没有选择opcache,它很棒,但已知其中一些优化会导致错误。
    • 如果这不起作用,即使您的代码可能较慢,请先尝试卸载opcache。
    • 如果其中任何一项更改或修复了问题,请更新您提交的错误报告。
  3. 立即停用所有不必要的扩展程序。
    • 开始单独启用所有扩展程序,在每次配置更改后进行彻底测试。
    • 如果您发现问题扩展,请使用更多信息更新您的错误报告。
  4. 利润。
  5. 可能没有任何利润......我在开始时说过,你可能会找到一种通过搞乱配置来改变你的症状的方法,但这是非常受欢迎和错过,并没有帮助下次有相同的zend_mm_heap corrupted消息时,只有很多配置选项。

    当我们发现错误时,我们创建错误报告非常重要,我们不能假设下一个遇到错误的人会去做...更可能的是,实际的解决方案是否定的如果你让合适的人知道这个问题,那就太神秘了。

    USE_ZEND_ALLOC

    如果在环境中设置USE_ZEND_ALLOC=0,则会禁用Zend自己的内存管理器; Zend的内存管理器确保每个请求都拥有它自己的堆,所有内存在请求结束时都是空闲的,并且针对大小合适的内存块进行了优化对于PHP。

    禁用它将禁用这些优化,更重要的是它可能会造成内存泄漏,因为有很多扩展代码依赖于Zend MM在请求结束时为它们释放内存(tut,tut)。

    它也可能隐藏症状,但系统堆可能会以与Zend堆完全相同的方式被破坏。

    它似乎更宽容或更不宽容,但修复问题的根本原因,它不能

    完全禁用它的能力是为了内部开发人员的利益;您应该从不部署PHP并禁用Zend MM。

答案 4 :(得分:22)

检查unset() s。确保在析构函数中没有unset()$this(或等价物)的引用,并且析构函数中的unset()不会导致对同一对象的引用计数降至0我做了一些研究,发现通常会导致堆损坏。

发生PHP bug report about the zend_mm_heap corrupted错误。有关如何重现它的示例,请参阅注释[2011-08-31 07:49 UTC] f dot ardelian at gmail dot com

我感觉所有其他“解决方案”(更改php.ini,使用更少的模块从源代码编译PHP等等)只是隐藏问题。

答案 5 :(得分:6)

对我来说,以前的答案都没有用,直到我尝试过:

opcache.fast_shutdown=0

到目前为止似乎有效。

我使用PHP 5.6与PHP-FPM和Apache proxy_fcgi,如果这很重要......

答案 6 :(得分:6)

在我的情况下,导致此错误的原因之一是阵列变得非常大。我已经设置了我的脚本以在每次迭代时重置数组并对问题进行排序。

答案 7 :(得分:5)

根据错误跟踪器,设置opcache.fast_shutdown=0。快速关闭使用Zend内存管理器来清理它的混乱,这会禁用它。

答案 8 :(得分:3)

我和这个问题搏斗了一个星期,这对我有用,或至少看起来好像

php.ini进行这些更改

report_memleaks = Off  
report_zend_debug = 0  

我的设置是

Linux ubuntu 2.6.32-30-generic-pae #59-Ubuntu SMP  
with PHP Version 5.3.2-1ubuntu4.7  

这不起作用。

所以我尝试使用基准测试脚本,并尝试记录脚本挂起的位置。 我发现在错误发生之前,一个php对象被实例化,并且完成对象应该做的事情需要3秒多的时间,而在之前的循环中它需要最多0.4秒。我跑了几次这个测试,每次都一样。我想的不是每次都创建一个新对象(这里有一个很长的循环),我应该重用该对象。到目前为止,我已经对脚本进行了十几次测试,内存错误已经消失了!

答案 9 :(得分:3)

我认为这里没有一个答案,所以我会添加我的经验。我看到了同样的错误以及随机的httpd段错误。这是一个cPanel服务器。有问题的症状是apache会随机重置连接(没有在chrome中收到数据,或者在firefox中重置了连接)。这些似乎是随机的 - 大部分时间都是有效的,有时却没有。

当我到达现场时,输出缓冲为OFF。通过阅读这个暗示输出缓冲的线程,我打开它(= 4096)看看会发生什么。此时,他们所有开始显示错误。这很好,因为错误现在是可重复的。

我经历了并开始禁用扩展程序。其中,eaccellerator,pdo,ioncube loader以及其他很多人怀疑,但都没有帮助。

我终于找到了淘气的PHP扩展名为“homeloader.so”,它似乎是某种cPanel-easy-installer模块。删除后,我没有遇到任何其他问题。

在该注释中,看起来这是一个通用的错误消息,因此您的milage将随所有这些答案而变化,您可以采取最佳行动:

  • 每次
  • 使错误可重复(什么条件?)
  • 找出共同因素
  • 有选择地禁用任何PHP模块,选项等(或者,如果你匆忙,将它们全部禁用以查看它是否有帮助,然后有选择地重新启用它们,直到它再次中断)。
  • 如果这没有帮助,许多这些答案暗示它可能是代码相关的。同样,关键是使错误可重复每个请求,以便缩小范围。如果您怀疑某段代码正在执行此操作,再次在错误可重复之后,只需删除代码,直到错误停止。一旦停止,你知道你删除的最后一段代码就是罪魁祸首。

如果没有完成上述所有操作,您还可以尝试以下方式:

  • 升级或重新编译PHP。希望修复导致问题的任何错误。
  • 将您的代码移至其他(测试)环境。如果这样可以解决问题,那会有什么变化? php.ini选项? PHP版本?等...
祝你好运。

答案 10 :(得分:2)

查找使用缓冲的任何模块,并有选择地禁用它。

我在CentOS 4.8上运行PHP 5.3.5,在这之后我发现eaccelerator需要升级。

答案 11 :(得分:2)

我在我拥有的服务器上也遇到过这个问题,根本原因是APC。我在php.ini文件中注释掉了“apc.so”扩展,重新加载了Apache,并且网站重新启动了。

答案 12 :(得分:2)

我已经尝试了以上所有内容和zend.enable_gc = 0 - 唯一的配置设置,这对我有帮助。

PHP 5.3.10-1ubuntu3.2与Suhosin-Patch(cli)(内置:2012年6月13日17:19:58)

答案 13 :(得分:2)

我认为很多原因都可能导致这个问题。在我的例子中,我将2个类命名为同一个名称,并且一个将尝试加载另一个类。

class A {} // in file a.php
class A // in file b.php
{
  public function foo() { // load a.php }
}

在我的案例中它会导致这个问题。

(使用laravel框架,运行php artisan db:seed in real)

答案 14 :(得分:2)

我使用PHP的Mongo 2.2驱动程序出现此错误:

$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField', 'yetAnotherField')); 

^^不工作

$collection = $db->selectCollection('post');
$collection->ensureIndex(array('someField', 'someOtherField')); 
$collection->ensureIndex(array('yetAnotherField')); 

^^工作! (?!)

答案 15 :(得分:2)

在PHP 5.3上,经过多次搜索,这是对我有用的解决方案:

我为此页添加了disabled the PHP garbage collection

<? gc_disable(); ?>

到问题页面的末尾,这使得所有错误都消失了。

source

答案 16 :(得分:1)

我遇到了同样的问题,当我的memcached会话的session.save_path的IP不正确时。将其更改为正确的IP修复了问题。

答案 17 :(得分:1)

如果您正在使用特征并且在课程之后加载特征(即自动加载的情况),您需要事先加载特征。

https://bugs.php.net/bug.php?id=62339

注意:这个bug非常随机;由于它的性质。

答案 18 :(得分:1)

对我来说问题是使用pdo_mysql。查询返回1960年的结果。我试图返回1900条记录并且有效。所以问题是pdo_mysql和太大的数组。我用原始的mysql扩展重写了查询并且它有效。

$link = mysql_connect('localhost', 'user', 'xxxx') or die(mysql_error());
mysql_select_db("db", $link);

Apache没有报告任何先前的错误。

zend_mm_heap corrupted
zend_mm_heap corrupted
zend_mm_heap corrupted
[Mon Jul 30 09:23:49 2012] [notice] child pid 8662 exit signal Segmentation fault (11)
[Mon Jul 30 09:23:50 2012] [notice] child pid 8663 exit signal Segmentation fault (11)
[Mon Jul 30 09:23:54 2012] [notice] child pid 8666 exit signal Segmentation fault (11)
[Mon Jul 30 09:23:55 2012] [notice] child pid 8670 exit signal Segmentation fault (11)

答案 19 :(得分:1)

“zend_mm_heap corrupted”表示内存管理问题。可以由任何PHP模块引起。 在我的情况下安装APC解决了。理论上,其他软件包如eAccelerator,XDebug等也可能有所帮助。或者,如果您安装了这种模块,请尝试将其关闭。

答案 20 :(得分:1)

我正在写一个php扩展,也遇到了这个问题。当我从我的扩展名调用具有复杂参数的extern函数时,会弹出此错误。

原因是我没有在extern函数中为参数(char *)分配内存。如果您正在撰写相同类型的扩展名,请注意这一点。

答案 21 :(得分:0)

很多人提到禁用XDebug来解决该问题。在很多情况下,这显然是不可行的,因为启用它是有原因的-调试代码。

我遇到了同样的问题,并注意到,如果我停止在IDE(PhpStorm 2019.1 EAP)中侦听XDebug连接,则会停止发生错误。

对我来说,实际的解决方法是删除所有现有的断点。

这可能是有效的解决方法,PhpStorm有时不能很好地删除断点,这些断点不再在外部更改文件(例如,通过git)后引用有效的代码行

编辑: 在xdebug问题跟踪器中找到了相应的错误报告: https://bugs.xdebug.org/view.php?id=1647

答案 22 :(得分:0)

这里的许多答案都很陈旧。对我来说(php 7.0.10通过Ondrej Sury&ucntu 14.04 16.04的PPA),问题似乎在于APC。我使用apc_fetch()等缓存了数百个小数据,当缓存一大块缓存时,我得到了错误。解决方法是切换到基于文件系统的缓存。

关于github https://github.com/oerdnj/deb.sury.org/issues/452#issuecomment-245475283的更多细节。

答案 23 :(得分:0)

如果有人以与我相同的方式解决这个问题,我想我会提供适合我的解决方案。

我在Windows上安装了php以外的驱动器( H:)。

在我的php.ini文件中,几个不同的文件系统变量的值被写成\path\to\directory - 如果我的安装在C:上,它将正常工作。

我需要将值更改为H:\path\to\directory。在我的php.ini文件中添加驱动器号的几个不同位置可以立即解决问题。我也确定(尽管我认为没有必要)在我的PEAR config中解决同样的问题 - 因为几个变量值也排除了那里的驱动器号。

答案 24 :(得分:0)

真正通过代码搜索无声错误。在我的Symfony应用程序中,从树枝基本模板中删除块后,我得到了zend_mm_heap损坏的错误,而不记得它是在子模板中引用的。没有抛出任何错误。

答案 25 :(得分:0)

在已升级到jessie的Debian服务器上有zend_mm_heap corruptedchild pid ... exit signal Segmentation fault。经过长时间的调查后发现,在Zend-Engine普遍可用之前就安装了XCache。

apt-get remove php5-xcacheservice apache2 restart后,错误消失了。

答案 26 :(得分:0)

我在本地开发中遇到了这个问题,同时使用 docker 和 php 的内置开发服务器和 Craft CMS。

我的解决方案是在 Craft 的会话中使用 Redis。

PHP 7.4

答案 27 :(得分:0)

上面已经编写了此选项,但我想带您逐步了解如何重现此错误。

简而言之。它帮助了我:

opcache.fast_shutdown = 0

我的旧配置:

  1. CentOS 6.9版(最终版)
  2. 带有Zend OPcache v7.0.6-dev的PHP 5.6.24(fpm-fcgi)
  3. Bitrix CMS

逐步:

  1. 运行phpinfo()
  2. 在输出中找到“ OPcache”。应该启用它。如果没有,那么此解决方案肯定对您没有帮助。
  3. 在任何地方执行opcache_reset()(感谢bug report,注释[2015-05-15 09:23 UTC] nax_hh at hotmail dot com)。在您的网站上加载多个页面。如果要归咎于OPcache,那么在nginx日志中将出现带有文本的行

104:对等连接重置

以及php-fpm日志中

zend_mm_heap损坏

然后在下一行

fpm_children_bury()

  1. 设置opcache.fast_shutdown=0(在/etc/php.d/opcache.ini文件中为我设置)
  2. 重新启动php-fpm(例如service php-fpm restart
  3. 再次加载您网站的某些页面。执行opcache_reset()并再次加载一些页面。现在应该没有错误。

顺便说一句。在phpinfo()的输出中,您可以找到OPcache的统计信息,然后优化参数(例如,增加内存限制)。 Good instructions用于调整opcache(俄语,但您可以使用翻译器)

答案 28 :(得分:0)

zend_mm_heap损坏的问题使我困惑了大约两个小时。首先,我禁用并删除了memcached,尝试了该问题的答案中提到的某些设置,并且在测试之后,这似乎与OPcache设置有关。我禁用了OPcache,问题消失了。之后,我重新启用了OPcache,对我来说

core notice: child pid exit signal Segmentation fault

zend_mm_heap corrupted

显然可以通过更改

解决
/etc/php.d/10-opcache.ini

我包括了在这里更改的设置; opcache.revalidate_freq = 2值得一提,我没有更改该值。

opcache.enable=1
opcache.enable_cli=0
opcache.fast_shutdown=0
opcache.memory_consumption=1024
opcache.interned_strings_buffer=128
opcache.max_accelerated_files=60000

答案 29 :(得分:0)

对我来说,是ZendDebugger导致内存泄漏并使MemoryManager崩溃。

我禁用了它,我正在寻找更新的版本。如果我找不到一个,我将切换到xdebug ...

答案 30 :(得分:0)

2014年11月13日PHP中修复了一个错误:

  

修复了错误#68365(在zend_hash_copy内存溢出后zend_mm_heap已损坏。)

在版本5.4.35,5.5.19和5.6.3中进行了更新。在我的情况下,当我从使用Ubuntu的官方可信包(5.5.9 + dfsg-1ubuntu4.14)改为由Ondrej Sury打包的5.5.30版本时,问题就消失了。没有其他解决方案适合我,我不想禁用opcache或抑制错误,因为这确实导致了段错误(500响应)。

Ubuntu 14.04 LTS:

export LANG=C.UTF-8       # May not be required on your system
add-apt-repository ondrej/php5
apt-get update
apt-get upgrade

答案 31 :(得分:0)

对我来说,是带有Xdebug的RabbitMq进入PHPStorm,所以&gt;设置/语言和框架/ PHP / Debug / Xdebug&gt;解开&#34;可以接受外部连接&#34;。

答案 32 :(得分:0)

我在这里的情况相同,上面没有任何帮助,并且更严肃地检查我发现我的问题,它包括在发送一些输出到缓冲区后尝试做死(header()),在代码中执行此操作的人忘了关于CakePHP资源并没有做出简单的“返回$ this-&gt;重定向($ url)”。

试图重新发明井,这就是问题所在。

我希望这有助于帮助某人!

答案 33 :(得分:0)

可能有助于某些人的一些提示

fedora 20,php 5.5.18

public function testRead() {
    $ri = new MediaItemReader(self::getMongoColl('Media'));

    foreach ($ri->dataReader(10) as $data) {
       // ...
    }
}

public function dataReader($numOfItems) {
    $cursor = $this->getStorage()->find()->limit($numOfItems);

    // here is the first place where "zend_mm_heap corrupted" error occurred
    // var_dump() inside foreach-loop and generator
    var_dump($cursor); 

    foreach ($cursor as $data) {
        // ...
        // and this is the second place where "zend_mm_heap corrupted" error occurred
        $data['Geo'] = [
            // try to access [0] index that is absent in ['Geo']
            'lon' => $data['Geo'][0],
            'lat' => $data['Geo'][1]
        ];
        // ...
        // Generator is used  !!!
        yield $data;
    }
}

使用var_dummp()实际上不是错误,它只是用于调试,将在生产代码中删除。但是发生zend_mm_heap的真正地方是第二位。

答案 34 :(得分:0)

由于没有其他答案解决它,我在php 5.4中遇到了这个问题,当我意外地运行了一个无限循环。

答案 35 :(得分:0)

对我来说问题是崩溃的memcached守护进程,因为PHP被配置为在memcached中存储会话信息。它正在吃100%的CPU,表现得很奇怪。 memcached启动后问题已经消失。

答案 36 :(得分:0)

在运行使用'&amp;'的旧代码时,我也注意到了这个错误和SIGSEGV在PHP 5.2 +中运行它时显式强制引用。

答案 37 :(得分:0)

设置

assert.active = 0 
php.ini中的

帮助了我(它关闭了php5UTF8库中的类型断言,zend_mm_heap corrupted消失了)

答案 38 :(得分:0)

在我的情况下,我忘了在代码中跟随:

);

我在这里和那里的代码中玩过并忘了它 - 在某些地方我有堆腐败,有些情况只是简单的'段错误:

[Wed Jun 08 17:23:21 2011] [notice] child pid 5720 exit signal Segmentation fault (11)

我在mac 10.6.7和xampp。

答案 39 :(得分:0)

因为我从未找到解决方案,所以我决定升级我的LAMP环境。我用PHP 5.3.x去了Ubuntu 10.4 LTS。这似乎已经为我解决了这个问题。

相关问题