131

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

操作系统:Fedora Core 8 阿帕奇:2.2.9 PHP:5.2.6

4

40 回答 40

57

经过反复试验,我发现如果我增加output_bufferingphp.ini 文件中的值,这个错误就会消失

于 2010-12-15T19:16:49.323 回答
55

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

更改配置选项有时会产生积极影响,但它也很容易使事情变得更糟,或者什么也不做。

错误的性质是这样的:

#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上打开错误报告
    • 如果您有段错误,请尝试提供回溯
    • 包含尽可能多的配置信息,特别是如果您使用 opcache 包含优化级别。
    • 继续检查错误报告以获取更新,可能会要求提供更多信息。
  2. 如果您已加载 opcache,请禁用优化
    • 我不是在选择 opcache,它很棒,但是已知它的一些优化会导致错误。
    • 如果这不起作用,即使您的代码可能较慢,请先尝试卸载 opcache。
    • 如果其中任何一项更改或修复了问题,请更新您所做的错误报告。
  3. 立即禁用所有不必要的扩展。
    • 开始单独启用所有扩展,在每次配置更改后进行彻底测试。
    • 如果您发现问题扩展,请使用更多信息更新您的错误报告。
  4. 利润。

可能没有任何利润...我一开始就说过,你也许可以通过弄乱配置来找到改变症状的方法,但这非常偶然,下次你有没有帮助同样的zend_mm_heap corrupted消息,只有这么多的配置选项。

当我们发现错误时创建错误报告真的很重要,我们不能假设下一个遇到错误的人会这样做......更有可能的是,如果你做出实际解决方案绝不是神秘的正确的人意识到这个问题。

USE_ZEND_ALLOC

如果你USE_ZEND_ALLOC=0在环境中设置,这会禁用 Zend 自己的内存管理器;Zend 的内存管理器确保每个请求都有自己的堆,所有内存在请求结束时都被释放,并且针对分配的内存块进行了优化,大小正好适合 PHP。

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

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

它可能看起来更宽容或更不宽容,但解决问题的根本原因,它不能

完全禁用它的能力是为了内部开发人员的利益;永远不要在禁用 Zend MM 的情况下部署 PHP。

于 2016-04-01T07:37:11.710 回答
50

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

opcache.enable_cli=0

一旦切换了 zend_mm_heap 损坏的错误就消失了。

于 2014-06-18T01:12:08.330 回答
44

如果您在 Linux 机器上,请在命令行上尝试此操作

export USE_ZEND_ALLOC=0
于 2012-04-10T15:48:00.267 回答
23

检查unset()s。确保您没有在析构函数中unset()引用$this(或等效项),并且析构函数中unset()的 s 不会导致对同一对象的引用计数降至 0。我做了一些研究,发现这通常是导致堆的原因腐败。

有一个关于 zend_mm_heap 损坏错误的 PHP 错误报告。[2011-08-31 07:49 UTC] f dot ardelian at gmail dot com有关如何重现它的示例,请参见评论。

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

于 2011-08-31T08:06:26.270 回答
13

对我来说,之前的答案都没有奏效,直到我尝试过:

opcache.fast_shutdown=0

到目前为止,这似乎有效。

我正在使用带有 PHP-FPM 和 Apache proxy_fcgi 的 PHP 5.6,如果这很重要的话......

于 2016-02-04T21:32:29.920 回答
6

就我而言,此错误的原因是其中一个数组变得非常大。我已经将我的脚本设置为在每次迭代时重置数组并对问题进行排序。

于 2012-04-24T10:10:45.050 回答
5

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

于 2016-10-22T17:47:18.703 回答
4

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

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

我经历并开始禁用扩展。其中,eaccellerator、pdo、ioncube loader 以及许多看似可疑但没有帮助的东西。

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

在那一点上,这似乎是一条通用错误消息,因此您的里程会因所有这些答案而异,您可以采取的最佳行动方案:

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

如果上述所有方法都失败,您还可以尝试以下操作:

  • 升级或重新编译 PHP。希望任何导致您的问题的错误都已修复。
  • 将您的代码移动到不同的(测试)环境。如果这解决了问题,那么发生了什么变化?php.ini 选项?PHP版本?ETC...

祝你好运。

于 2013-08-22T02:47:45.493 回答
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 秒。我多次运行这个测试,每次都一样。我认为不是每次都创建一个新对象(这里有一个很长的循环),我应该重用该对象。到目前为止,我已经测试了十几次脚本,内存错误已经消失了!

于 2011-04-23T14:52:50.367 回答
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)

于 2014-02-09T05:14:37.433 回答
2

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

于 2011-07-05T16:31:32.410 回答
2

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

我通过添加以下内容禁用了此页面的 PHP 垃圾收集:

<? gc_disable(); ?>

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

来源

于 2013-03-03T15:02:02.987 回答
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')); 

^^ 工作!(?!)

于 2012-11-12T18:43:02.860 回答
2

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

带有 Suhosin-Patch (cli) 的 PHP 5.3.10-1ubuntu3.2(构建时间:2012 年 6 月 13 日 17:19:58)

于 2012-08-28T06:25:43.927 回答
2

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

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

于 2011-02-13T23:33:30.400 回答
1

“zend_mm_heap 已损坏”表示内存管理存在问题。可能由任何 PHP 模块引起。就我而言,安装 APC 成功了。理论上,其他软件包如 eAccelerator、XDebug 等也可能有所帮助。或者,如果您安装了此类模块,请尝试将其关闭。

于 2013-11-25T07:12:32.310 回答
1

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

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

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

于 2012-06-25T08:01:03.133 回答
1

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

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

于 2013-12-30T07:38:09.400 回答
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)
于 2012-07-30T07:45:11.010 回答
1

我遇到了同样的问题,并且当我的 session.save_path 用于 memcached 会话的 IP 不正确时。将其更改为正确的 IP 可以解决问题。

于 2011-06-29T19:30:21.453 回答
1

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

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

对我来说,实际的修复是删除任何现有的断点。

这是一个有效修复的可能性是,PhpStorm 有时不擅长删除在外部更改文件后不再引用有效代码行的断点(例如通过 git)

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

于 2019-04-09T01:52:40.713 回答
1

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
于 2020-11-28T02:36:21.333 回答
0

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

于 2012-10-18T05:47:32.923 回答
0

就我而言,我忘记了以下代码:

);

我到处玩弄,在这里和那里的代码中忘记了它 - 在某些地方我遇到了堆损坏,有些情况只是简单的 ol' seg 错误:

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

我在 mac 10.6.7 和 xampp 上。

于 2011-06-08T14:27:09.037 回答
0

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

于 2013-05-10T07:36:47.567 回答
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 真正发生的地方是第二个地方。

于 2014-11-10T08:29:19.037 回答
0

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

于 2010-10-25T16:44:22.230 回答
0

我在这里遇到同样的情况,上面没有任何帮助,更认真地检查我发现了我的问题,它包括在将一些输出发送到缓冲区后尝试做 die(header()),在代码中这样做的人忘记了 CakePHP 资源并没有做一个简单的“return $this->redirect($url)”。

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

我希望这对某人有所帮助!

于 2015-03-27T21:09:26.820 回答
0

环境

assert.active = 0 

在 php.ini 中对我有帮助(它关闭了php5UTF8库中的类型断言并zend_mm_heap corrupted消失了)

于 2012-05-22T20:13:04.737 回答
0

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

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

于 2010-08-09T08:37:56.260 回答
0

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

于 2014-08-29T21:31:26.497 回答
0

真正在你的代码中寻找一个无声的错误。在我的 Symfony 应用程序中,从 twig 基本模板中删除一个块后,我得到了 zend_mm_heap 损坏的错误,但不记得它在子模板中被引用。没有抛出错误。

于 2017-04-19T01:15:36.810 回答
0

如果其他人以与我相同的方式遇到此问题,我想我会提供对我有用的解决方案。

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

在我的 php.ini 文件中,几个不同的文件系统变量的值是这样写的 \path\to\directory——如果我的安装在C:.

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

于 2016-05-13T14:23:34.260 回答
0

在升级到 jessie 的 Debian 服务器上zend_mm_heap corruptedchild pid ... exit signal Segmentation fault经过长时间的调查,事实证明 XCache 是在 Zend-Engine 普遍可用之前安装的。

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

于 2017-06-01T13:00:15.117 回答
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
于 2015-11-19T20:06:22.837 回答
0

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

我的解决方案是使用 Redis 进行 Craft 的会话。

PHP 7.4

于 2021-02-07T01:33:53.747 回答
0

这个选项已经在上面写过了,但是我想引导你完成我如何重现这个错误的步骤。

简要地。它帮助了我:

opcache.fast_shutdown = 0

我的旧配置:

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

一步步:

  1. phpinfo()
  2. 在输出中找到“OPcache”。它应该被启用。如果没有,那么这个解决方案肯定不会帮助你。
  3. 在任何地方执行opcache_reset()(感谢错误报告、评论[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 的统计信息,然后优化参数(例如,增加内存限制)。调整 opcache 的良好说明(俄语,但您可以使用翻译器)

于 2020-11-20T15:47:57.450 回答
0

对我来说,它是带有 Xdebug 的 RabbitMq 进入 PHPStorm,所以 > 设置/语言和框架/PHP/Debug/Xdebug > 取消勾选“可以接受外部连接”。

于 2015-10-07T16:33:53.790 回答
0

这里的许多答案都是旧的。对我来说(通过 Ondrej Sury 在 ubuntu 14.04和16.04上的 PPA 的 php 7.0.10 )问题似乎出在 APC 上。我正在使用 apc_fetch() 等缓存数百个小数据位,当使缓存的一块无效时,我会收到错误消息。解决方法是切换到基于文件系统的缓存。

github https://github.com/oerdnj/deb.sury.org/issues/452#issuecomment-245475283上的更多详细信息。

于 2016-09-08T04:05:07.513 回答