「zend_mm_heap破損」の意味


126

突然、アプリケーションでこれまでにないほどの問題が発生しました。Apacheのエラーログを確認することにしたところ、「zend_mm_heapが破損しています」というエラーメッセージが見つかりました。これは何を意味するのでしょうか。

OS:Fedora Core 8 Apache:2.2.9 PHP:5.2.6


2
私が使用したUSE_ZEND_ALLOC=0エラー・ログにスタックトレースを取得するには、バグを発見し/usr/sbin/httpd: corrupted double-linked list、私はコメントアウトすることが分かったopcache.fast_shutdown=1私のために働きました。
Spidfire 2015年

はい、同じです。また、stackoverflow.com
a / 35212026/35946の

Laravelを使用して同じことをしました。クラスを別のクラスのコンストラクターに注入しました。私が注入していたクラスは、それが注入されたクラスを注入しており、基本的には循環参照を作成してヒープの問題を引き起こしていました。
Thomas

1
最短かつ一時的な解決策として、Apacheサーバーを再起動します:)
Leopathu

回答:


52

多くの試行錯誤の末、output_bufferingphp.iniファイルの値を大きくすると、このエラーは解消されることがわかりました


59
何に増やす?この変更により、このエラーが解消されるのはなぜですか?
JDS

2
この答えは、それは助けることができる増え何にoutput_bufferingがあると理由を説明するのに役立ちます@JDS stackoverflow.com/a/2832179/704803を
andrewtweber

8
@andrewtweberわかりました。opと同じエラーメッセージが表示されていたため、dsmithersの回答から除外された特定の詳細について疑問に思っていました。クロージャーについて:私の問題は、memcachedに関連する誤って構成された設定であることが判明しました。感謝します!
JDS 2012年

@JDS誤って構成された設定は何ですか?
カイルクローニン

3
@KyleCronin当社のサービスプラットフォームでは、本番環境でMemcacheを使用しています。ただし、一部の単一インスタンス(非本番/サンドボックス、お客様の1回限り)では、memcacheを使用しません。後者の場合、本番環境からお客様に1回限りの構成をコピーしましたが、memcache構成は、その環境では使用できないmemcacheサーバーURIを示していました。アプリで行を削除してmemcacheを無効にしたところ、問題は解消しました。つまり、話は短く、特定の環境で発生する非常に具体的な問題であり、一般的には適用できない場合があります。しかし、あなたが尋ねたので...
JDS

47

これは、構成オプションを変更することで必ず解決できる問題ではありません。

設定オプションを変更すると、プラスの影響が出る場合がありますが、それと同じくらい簡単に事態が悪化したり、何も起こらない場合もあります。

エラーの性質はこれです:

#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を使用)ため、実行時にプログラムが使用できるメモリ領域を指します。

ひどいコードをいじってみると、明らかに正しくないステートメントのすべてがセグメンテーション違反(致命的な終了エラー)になるわけではないことがわかります。

サンプルコードでこれらのエラーを明示的に作成しましたが、メモリ管理環境では同じ種類のエラーが非常に簡単に発生します。たとえば、一部のコードが変数(または他のシンボル)の参照カウントを正しい方法で維持していない場合、たとえば解放が早すぎると、別のコードがすでに解放されたメモリから読み取られる可能性があり、何らかの理由でアドレスが誤って格納されると、別のコードが無効なメモリに書き込まれる可能性があり、2回解放される可能性があります...

これらは、PHPでデバッグできる問題ではなく、内部開発者の注意が絶対に必要です。

行動方針は次のとおりです。

  1. http://bugs.php.netでバグレポートを開きます
    • セグメンテーション違反がある場合は、 バックトレース
    • 特にopcache include最適化レベルを使用している場合は、適切と思われるだけの構成情報を含めます。
    • バグレポートで更新を確認し続けてください。詳細が要求される場合があります。
  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をデプロイしないでください。


根本的な問題は、実行しているPHPのバージョンである可能性がありますか?
イシュマエル

@Ishmaelはい、すべての拡張機能のバージョン。警告は拡張機能から発生する可能性があるため。
ビショップ

2
この答えは私にとって最良のようです。私は個人的にこの問題を何度か経験しましたが、それは常に欠陥のある拡張子(私の場合、Enchantスペルライブラリ)に関連していました。php自体以外にも、環境が悪い可能性があります(libバージョンの不一致、誤った依存関係など)
Fractalizer

1
これまでのところ、この質問および他の多くの同様の質問に対する最良の答え
Nikita

この答えは確かに有益ですが、サーバーコアをデバッグするのはアプリケーション開発者の仕事ではないと私は思います。確かに、完全なスタックトレースがあればもっと簡単ですが、次は何ですか?プルリクエストで修正するように依頼しますか?誰もがCのような低レベルの言語に精通している、または理解できるわけではありません。逆も当てはまります。したがって、結局のところ、開発者がそもそもメモリ管理エラーを起こさないほうがはるかに簡単だと思います。あなたが示唆するように、これはopcacheである程度一般的ですが、一部の開発者が開発方法を知っているので、驚くべきことではありません。
job3dot5

46

PHP 5.5でもこれと同じエラーが発生し、出力バッファリングを増やしても解決しませんでした。私もAPCを実行していなかったので、それは問題ではありませんでした。最終的にopcacheまで追跡しましたが、cliから無効にする必要がありました。これには特定の設定がありました:

opcache.enable_cli=0

いったん切り替えると、zend_mm_heapの破損エラーは解消されました。


同じ問題と解決策はこちら!ありがとう!
MauricioSánchez14年

2
この投稿の巨大なプラス1。私たちはすべてを試しましたが、結局これだけがうまくいきました。
ジェフリーブライア2015

7
cliはphpのコマンドラインバージョンであり、たとえばapache Webサーバーで使用されるphpモジュールとは何の関係もないことを知っていると思います。cliでopcacheを無効にするとどのように役立つのか知りたいです。(これはWebサーバーで発生していると思います)
BIOHAZARD

@ BioHazard、cliのほかに、一般的な設定opcache.enable = 0があります。しかし、それはケースを助ける必要はありません
コンスタンティン・イワノフ

これは、この質問に対する回答として受け入れられるはずです。php.iniのドキュメントによると、output_bufferingを上げることは答えではありません。これは、Webサイトまたはアプリケーションに悪影響を与える可能性があるためです。
BlueCola 2017年

41

Linuxボックスを使用している場合は、コマンドラインでこれを試してください

export USE_ZEND_ALLOC=0

これは私を救った!これをphp-
fpm

これでうまくいきました。/etc/apache2/envvarsppas(apt)からapacheとphpの両方をインストールしたubuntuサーバーでこれを実行している場合は、この行を忘れずに追加してください。PHP 7.0-RC4は、ondrejのリポジトリからインストールしたときに、このエラーをスローし始めました。
Pedro Cordeiro

:そしてまた、それはWindows上の作品だset USE_ZEND_ALLOC=0
ナビKAZ

22

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をコンパイルするなど)は問題を隠しているだけだと感じています。


6
私はこの問題を単純なHTML DOMで取得していて、未設定から$ simplehtmldom-> clear()に変更して、問題を解決しました、ありがとう!
alexkb 2013

9

私が試すまで、私にとって以前の答えはどれもうまくいきませんでした:

opcache.fast_shutdown=0

これは今のところうまくいくようです。

PHP 5.6とPHP-FPMおよびApache proxy_fcgiを使用しています(問題がある場合)。


1
すべての異なるシナリオに対して「私も」という応答がたくさんありますが、これは私の構成に最も似ていて、好評でした-この正確な変更により、私の問題は解消されたようです。
lkraav 2016年

6

私の場合、このエラーの原因は、配列の1つが非常に大きくなることでした。反復ごとに配列をリセットするようにスクリプトを設定して、問題を分類しました。


これでうまくいきました-ありがとう!ガベージコレクターが循環参照のメモリを解放するとは思わなかったので、チェックしませんでした。
ハーフ速い

5

バグトラッカーに従って、を設定しopcache.fast_shutdown=0ます。高速シャットダウンでは、Zendメモリマネージャを使用して混乱を解消します。これにより、これが無効になります。


これにより、CentOS Linuxリリース7.2.1511、PHP 5.5.38で「zend_mm_heapが破損」した問題が修正されました。これで、オペコードキャッシュの使用を再開できます。それなしで昼と夜。
Richard Ginsberg

リマインダーをありがとう、これはまさに私の問題でした!
ウィースラー2017

4

ここに1つの答えはないと思いますので、私の経験を追加します。私はこれと同じエラーをランダムなhttpd segfaultsとともに見ました。これはcPanelサーバーでした。問題の症状は、Apacheがランダムに接続をリセットすることでした(Chromeでデータが受信されなかったか、Firefoxで接続がリセットされました)。これらは一見ランダムでした-ほとんどの場合、うまくいきましたが、うまくいかないこともあります。

シーンに到着したとき、出力バッファリングはオフでした。出力のバッファリングをほのめかすこのスレッドを読むことで、私はそれをオン(= 4096)にして何が起こるかを確認しました。この時点で、全員がエラーを表示し始めました。エラーが再現できるようになったので、これは良かったです。

私は通り抜け、拡張機能を無効にし始めました。その中には、eaccellerator、pdo、ioncube loader、そして疑わしいと思われるたくさんのものありますが、どれも助けにはなりませんでした。

私はついにいたずらなPHP拡張機能を「homeloader.so」として見つけました。これはある種のcPanel-easy-installerモジュールのようです。削除後、他の問題は発生していません。

そのメモでは、これは一般的なエラーメッセージであるように思われるので、これらのすべての回答、つまり実行できる最善策として、あなたの走行距離は異なります。

  • 毎回エラーを再現可能にします(どのような条件ですか?)
  • 共通要因を見つける
  • PHPモジュール、オプションなどを選択的に無効にします(または、急いでいる場合は、それらをすべて無効にして、それが役立つかどうかを確認してから、再び機能しなくなるまで選択的に再度有効にします)。
  • これが役に立たない場合、これらの回答の多くは、コードが解放されている可能性があることを示唆しています。繰り返しますが、重要なのは、エラーをすべてのリクエストで再現可能にして、それを絞り込むことができるようにすることです。コードの一部がこれを実行していると思われる場合は、エラーが繰り返し発生した後、エラーが停止するまでコードを削除してください。停止すると、最後に削除したコードが原因であることがわかります。

上記のすべてに失敗した場合、次のようなことも試すことができます。

  • PHPのアップグレードまたは再コンパイル。問題の原因となっているバグが修正されていることを願っています。
  • コードを別の(テスト)環境に移動します。これで問題が解決した場合、何が変わりましたか?php.iniオプション?PHPバージョン?等...

幸運を。


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秒かかりました。私はこのテストを何度も実行しましたが、毎回同じでした。毎回新しいオブジェクトを作成する代わりに(ここでは長いループがあるため)、オブジェクトを再利用する必要があると思いました。これまでに数十回以上スクリプトをテストしましたが、メモリエラーは解消されました。


1
これはしばらく機能しましたが、エラーが戻ってきました。どうすればこれを停止できますか?
sam

これは、MAMP PRO 2.1.1を搭載したMacマーベリックスで私にとってはうまくいきました。
MutantMahesh 14

この解決策は問題を完全に解決しませんでした。このエラーが再び発生し始めます。
MutantMahesh 2014

7
確かにこれは問題を修正するのではなく、エラーのレポートをオフにするだけですか?
Robert Went 2015

2

バッファリングを使用するモジュールを探し、それを選択的に無効にします。

CentOS 4.8でPHP 5.3.5を実行しています。これを実行した後、eacceleratorのアップグレードが必要であることがわかりました。


2

私が所有するサーバーでもこの問題が発生しました。根本的な原因はAPCでした。php.iniファイルの "apc.so"拡張機能をコメントアウトし、Apacheをリロードすると、サイトはすぐに復旧しました。


2

私は上記のすべてを試しましたzend.enable_gc = 0-唯一の構成設定は、私を助けました。

PHP 5.3.10-1ubuntu3.2とSuhosin-Patch(cli)(ビルド:2012年6月13日17:19:58)


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')); 

^^ WORKS!(?!)


この回答は、Mongoの問題の道筋をたどってデバッグするのに役立ちました。私の場合、PHP 5.6 + Mongo 1.6.9ドライバー、以前に入力された配列からの値の反復およびクエリ時にzend_mm_heap破損メッセージがスローされましたforeach(selectCollection()->find()) { $arr = .. }
Mihai MATEI

2

PHP 5.3では、たくさんの検索を行った後、これが私にとってうまくいった解決策です:

次のコードを追加して、このページのPHPガベージコレクション無効にしました。

<? gc_disable(); ?>

問題のあるページの終わりまで、すべてのエラーが消えました。

ソース


2

多くの理由がこの問題を引き起こす可能性があると思います。そして私の場合、私は2つのクラスに同じ名前を付け、1つは別のものをロードしようとします。

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

そしてそれは私の場合この問題を引き起こします。

(laravelフレームワークを使用して、php artisan db:seedを実際に実行)


1

これと同じ問題があり、memcachedセッションのsession.save_pathに間違ったIPがあった場合。正しいIPに変更すると、問題が解決しました。


1

トレイトを使用していて、クラスの後にトレイトが読み込まれる場合(つまり、オートロードの場合)、事前にトレイトを読み込む必要があります。

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

注:このバグは非常にランダムです。その性質のために。


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)

1

「zend_mm_heapの破損」は、メモリ管理の問題を意味します。PHPモジュールが原因である可能性があります。私の場合、APCのインストールはうまくいきました。理論的には、eAccelerator、XDebugなどの他のパッケージも役立ちます。または、そのようなモジュールがインストールされている場合は、それらのスイッチをオフにしてみてください。


1

私はphp拡張を書いていて、この問題も発生します。拡張機能から複雑なパラメーターを使用してextern関数を呼び出すと、このエラーがポップアップ表示されます。

その理由は、extern関数のパラメーター(char *)にメモリを割り当てていないためです。同じ種類の拡張機能を作成している場合は、これに注意してください。


0

私にとって、メモリリークを引き起こし、MemoryManagerがクラッシュするのはZendDebuggerでした。

私はそれを無効にし、現在新しいバージョンを探しています。見つからない場合は、xdebugに切り替えます...


0

これに対する解決策が見つからなかったので、LAMP環境をアップグレードすることにしました。PHP 5.3.xでUbuntu 10.4 LTSに行きました。これで問題が解決したようです。


0

私の場合、コードで次のことを忘れていました:

);

私は遊んで、コードのあちこちでそれを忘れました-いくつかの場所でヒープが破損しました。

[2011年6月8日水曜日17:23:21] [通知]子pid 5720終了信号のセグメンテーションエラー(11)

Mac 10.6.7とxamppを使用しています。


0

また、PHP 5.2以降で実行中に「&」を使用して明示的に参照を強制する古いコードを実行すると、このエラーとSIGSEGVにも気づきました。


0

設定

assert.active = 0 

php.iniで私を助けました(php5UTF8ライブラリの型アサーションをオフにして、消えzend_mm_heap corruptedました)


0

PHPがmemcachedにセッション情報を格納するように構成されていたため、私にとって問題はmemcachedデーモンのクラッシュでした。それは100%のCPUを食べていて、奇妙な行動をしていました。memcachedの再起動後に問題が発生しなくなりました。


0

他の回答のどれもそれに対処しなかったので、誤って無限ループを実行したときに、php 5.4でこの問題が発生しました。


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が発生した実際の場所は2番目です。


0

私はここで同じ状況にあり、何も助けにならなかった、そしてより深刻にチェックして問題を見つけた、それはバッファに出力を送信した後にtry do die(header())で構成され、コードでこれを行った人はCakePHPのリソースを忘れていましたシンプルな「return $ this-> redirect($ url)」を作成しませんでした。

井戸を再発明しようとして、これが問題でした。

これが誰かを助けることを願っています!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.