“ zend_mm_stack 已损坏”是什么意思

突然之间,我的申请出现了前所未有的问题。我决定检查 Apache 的错误日志,发现了一条错误消息,说“ zend _ mm _ heap 已损坏”。这是什么意思。

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

180128 次浏览

对我来说,正是 ZendDebugger 导致了内存泄漏,并导致了内存管理器崩溃。

我关闭了它,现在正在寻找更新的版本。如果找不到,我就切换到 xdebug..。

因为我从来没有找到一个解决方案,我决定升级我的 LAMP 环境。我用 PHP 5.3. x 访问了 Ubuntu 10.4 LTS。这似乎为我解决了问题。

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

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

我在 CentOS 4.8上运行 PHP 5.3.5,这样做之后,我发现电子加速器需要升级。

我为这个问题纠结了一个星期,这对我有用,至少看起来是这样

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秒。我做了好几次这个测试,每次都一样。我认为,与其每次都创建一个新对象(这里有一个很长的循环) ,我应该重用这个对象。到目前为止,我已经测试了这个脚本十几次,内存错误已经消失了!

在我的情况下,我忘记了下面的代码:

);

I played around and forgot it in the code here and there - in some places i got heap corruption, some cases just plain ol' seg fault:

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

我用的是 Mac 10.6.7和 Xampp。

我遇到过同样的问题,当 memcached 会话的 session.save _ path 出现不正确的 IP 时。改变它到正确的 IP 固定的问题。

我自己的服务器上也有这个问题,根本原因是 APC。我注释掉了 php.ini 文件中的“ apc.so”扩展名,重新加载了 Apache,这些站点立即恢复了。

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

有一个 关于 zend _ mm _ heap 损坏的 PHP 错误报告错误。请参阅注释 [2011-08-31 07:49 UTC] f dot ardelian at gmail dot com中关于如何重现该错误的示例。

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

如果您使用的是 Linux 机器,请在命令行上尝试这个操作

export USE_ZEND_ALLOC=0

在我的例子中,出现这个错误的原因是其中一个数组变得非常大。我已经将脚本设置为在每次迭代时重置数组,这样就解决了问题。

设置

assert.active = 0

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

如果您正在使用 trait,而 trait 是在类之后加载的(即。你需要预先加载 trait。

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

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

对我来说,问题在于使用 pdo _ mysql。查询返回了1960年的结果。我试图归还1900张唱片,它奏效了。所以问题是 pdo _ mysql 和太大的数组。我用原始的 mysql 扩展重写了 query,它工作了。

$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)

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

PHP 5.3.10-1ubuntu3.2 with Suhosin-Patch (cli)(build: Jun 13201217:19:58)

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

我在使用 Mongo 2.2的 PHP 驱动程序时出现了以下错误:

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

^ ^ 没用

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

^ ^ 工作! (? !)

在 PHP 5.3上,经过大量的搜索,我找到了下面这个解决方案:

我已经为这个页面通过添加 禁用了 PHP 垃圾回收:

<? gc_disable(); ?>

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

资料来源。

对我来说,问题是 memcached 守护进程崩溃了,因为 PHP 被配置为在 memcached 中存储会话信息。它吃了100% 的中央处理器,行为怪异。在 memcached 重新启动问题已经消失。

我不认为这里有一个答案,所以我要加上我的经验。我看到同样的错误以及随机 httpd Segfault。这是一个 cPanel 服务器。问题的症状是 Apache 会随机重置连接(在 chrome 中没有接收到数据,或者在 firefox 中重置连接)。这些看起来都是随机的——大多数时候它是有效的,有时候不是。

当我到达现场输出缓冲是关闭的。通过读取这个线程(它暗示了输出缓冲) ,我打开了它(= 4096) ,看看会发生什么。在这一点上,他们 所有开始显示错误。这是好事,现在错误是可重复的。

我检查了一遍,然后开始禁用分机。其中,加速器,pdo,离子立方加载器,和大量的 看过怀疑,但没有帮助。

我最后发现了一个名为“ homeloader.so”的 PHP 扩展,它看起来像是某种 cPanel 易于安装的模块。除此之外,我没有遇到任何其他问题。

在这一点上,它似乎是一个通用的错误信息,所以你的里程将不同的所有这些答案,最好的行动方针,你可以采取:

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

如果以上所有方法都失败了,你也可以尝试这样的方法:

  • 升级或重新编译 PHP。希望导致问题的 bug 已经修复。
  • 将代码移动到不同的(测试)环境。如果这解决了问题,那么是什么改变了呢?Php.ini 选项?PHP 版本?等等。.

祝你好运。

“ zend _ mm _ heap 已损坏”是指内存管理方面的问题。任何 PHP 模块都可能导致这种问题。 在我的情况下,安装 APC 解决了。理论上,其他的软件包,比如电子加速器、 XDebug 等也可能有所帮助。或者,如果您已经安装了这类模块,请尝试关闭它们。

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

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

我认为很多原因会导致这个问题。在我的例子中,我命名了两个相同名称的类,其中一个将尝试加载另一个。

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

在我的案子里,这就是问题所在。

(使用 laravel 框架,运行 php artian db: kind in real)

我在 PHP 5.5下得到了同样的错误,增加输出缓冲区并没有帮助。我也没有运行装甲运兵车,所以这不是问题所在。我最终追踪到 Opcache,我只需要从 cli 中禁用它。有一个特定的设置:

opcache.enable_cli=0

一旦切换了 zend _ mm _ stack,损坏的错误就消失了。

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

一些可能对某人有帮助的提示

软呢帽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 _ dump ()实际上不是一个错误,它只是为了调试而放置,并且将在生产代码中删除。但是发生 zend _ mm _ stack 的实际位置是第二个位置。

我在这里也遇到了同样的情况,没有什么以上的帮助,并检查更严重的我发现我的问题,它包括在尝试做模具(header ())后发送一些输出到 buffer,在代码中这样做的人忘记了 CakePHP 资源,并没有做一个简单的“返回 $this-> 重定向($url)”。

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

我希望这个联系帮助有人!

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

2014年11月13日,PHP 修复了一个 bug:

修正了 bug # 68365(zend _ mm _ heap 在 zend _ hash _ copy 中内存溢出后损坏)。

这是在5.4.35.5.5.19和5.6.3版本中更新的。在我的例子中,当我从使用 Ubuntu 的官方可靠软件包(5.5.9 + dfsg-1ubuntu4.14)改为使用 Ondrej Sury 打包的5.5.30版本时,问题就消失了。没有其他解决方案对我有效,我不想禁用 opcache 或抑制错误,因为这确实会导致 Segfault (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

对我来说,以前的答案都不管用,直到我尝试了:

opcache.fast_shutdown=0

目前看来还不错。

我正在使用 PHP 5.6和 PHP-FPM 以及 Apache xy _ fcgi,如果这很重要的话..。

这个问题不一定可以通过更改配置选项来解决。

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

错误的性质是这样的:

#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

在与瓦尔格林一起执行代码时,你会看到许多内存错误,最终导致一个内存区段错误:

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. 在 < a href = “ http://bugs.php.net”> http://bugs.php.net 上打开 bug 报告
    • 如果有一个 Segfault,请尝试提供一个 反向追踪
    • 特别是在使用 opcache Include 优化级别时,尽可能多地包含适当的配置信息。
    • 继续检查 bug 报告以获得更新,可能会请求更多信息。
  2. 如果已经加载了 opcache,请禁用优化
    • 我不是针对 opcache,它很棒,但是它的一些优化已经被认为会导致错误。
    • 如果这不起作用,即使您的代码可能比较慢,尝试先卸载 opcache。
    • 如果任何此类更改或修复了问题,请更新所做的错误报告。
  3. 立即禁用 所有不必要的扩展。
    • 开始单独启用所有扩展,在每次配置更改后进行全面测试。
    • 如果您发现问题扩展,更新您的错误报告与更多的信息。
  4. 利润。

可能没有任何好处... ... 我在开始时说过,你也许能够通过扰乱配置来找到改变症状的方法,但这是极其偶然的,并且在下一次你有相同的 zend_mm_heap corrupted消息时没有帮助,只有这么多的配置选项。

当我们发现 bug 的时候,我们创建 bug 报告是非常重要的,我们不能假设下一个发现 bug 的人会这么做... ... 更有可能的是,如果你让正确的人意识到这个问题,实际的解决方法并不神秘。

USE _ ZEND _ ALLOC 使用 _ ZEND _ ALLOC

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

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

它也可能出现 藏起来的症状,但是系统堆的损坏方式与 Zend 的堆完全相同。

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

禁用它的能力对于内部开发人员来说是有好处的; 您应该在禁用 Zend MM 的情况下 永远不会部署 PHP。

万一有人和我一样有这个问题,我想我可以提供一个对我有效的解决方案。

我有 php安装在 Windows 上的驱动器,而不是我的系统驱动器(H:)。

在我的 php.ini 文件中,几个不同文件系统变量的值被写成类似于 \path\to\directory的值——如果我的安装在 C:上,这个值就可以很好地工作。

我需要将值改为 H:\path\to\directory。在我的 php.ini文件中添加驱动器号几个不同的地方立即修复了这个问题。我还确保(虽然我不认为这是必要的) ,以解决同样的问题,在我的 PEAR config-因为几个变量值排除驱动器的字母也有。

这里的许多答案都很古老。对我来说(php 7.0.10 via Ondrej Sury’s PPA on ubuntu 14.04 还有16.04)问题似乎在于 APC。我使用 apc _ catch ()等缓存了数百个小数据块,当使缓存块失效时,我会得到错误消息。解决办法是切换到基于文件系统的缓存。

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

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

在代码中查找无声错误。在我的 Symfony 应用程序中,我从一个树枝基模板中删除了一个块,但是没有记住它是在子模板中引用的,因此得到了 zend _ mm _ stack 损坏错误。没有抛出错误。

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

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

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

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

对我来说,实际的补救措施是删除所有现有的断点。

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

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

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

很短暂,对我有帮助:

opcache.fast_shutdown = 0

我的遗留配置:

  1. CentOS 版本6.9(最终版)
  2. PHP 5.6.24(fpm-fcgi)和 Zend OPcache v7.0.6-dev
  3. 碧翠丝 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 (俄语,但可以使用翻译器)

Zend _ mm _ stack 损坏的问题困扰了我几个小时。首先,我禁用并删除 memcached,尝试了这个问题的答案中提到的一些设置,在测试之后,这似乎是 OPcache 设置的一个问题。我关闭了 OPcache 问题就解决了。之后,我重新启用了 OPcache,对我来说

core notice: child pid exit signal Segmentation fault

还有

zend_mm_heap corrupted

显然是通过改变来解决的

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

我包含了我在这里修改的设置; opcache.revalid_ 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

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

我的解决方案是在 Craft 的课程中使用 Redis。

PHP 7.4

在我的例子中,Apache 没有启动,因为 zend _ mm _ stack 损坏问题

sudo emacs /etc/apache2/mods-enabled/php7.2.load

注释这句话

# LoadModule php7_module /usr/lib/apache2/modules/libphp7.2.so

让阿帕奇正常工作。所以我知道问题出在 php。我安装了不止一个 php,即 php 7.2和 php 8。我的站点使用的是 php7.2(所以我必须使用 php7.2)。单个 php 没有任何问题。但是安装其他(后来的)版本会以某种方式改变一些东西,从而导致 zend _ mm _ stack 损坏问题。清除和安装并不能解决问题。

解决方案是我禁用了错误的 php 版本,我禁用的是 php8.0,而我安装的是 php8.1。

sudo a2dismod php8.0

将 php8.0更改为 php8.1解决了所有问题

sudo a2dismod php8.1