web-dev-qa-db-ja.com

「zend_mm_heap破損」とはどういう意味ですか

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

OS:Fedora Core 8 Apache:2.2.9 PHP:5.2.6

122
bkulyk

多くの試行錯誤の後、php.iniファイルのoutput_buffering値を増やすと、このエラーがなくなることがわかりました。

51
dsmithers

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

opcache.enable_cli=0

切り替えると、zend_mm_heap破損エラーはなくなりました。

46
Justin MacLeod

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

構成オプションを変更すると、良い結果が得られる場合がありますが、状況を悪化させるか、まったく何もしないことがあります。

エラーの性質は次のとおりです。

#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 のバグレポートを開きます。
    • セグメンテーション違反がある場合は、 backtrace を指定してください。
    • 特に、opcacheを使用している場合は、最適化レベルを含めて、適切と思われるだけの構成情報を含めます。
    • バグレポートの更新を確認してください。詳細情報が要求される場合があります。
  2. Opcacheがロードされている場合、最適化を無効にします
    • 私はopcacheを選択していません。それは素晴らしいことですが、その最適化のいくつかは障害を引き起こすことが知られています。
    • コードが遅くても動作しない場合は、まずopcacheをアンロードしてみてください。
    • このいずれかが問題を変更または修正する場合は、作成したバグレポートを更新します。
  3. 不要な拡張機能を一度に無効化all
    • すべての拡張機能を個別に有効にし始め、各構成変更後に徹底的にテストします。
    • 問題の拡張を見つけた場合は、バグレポートを更新して詳細情報を入手してください。
  4. 利益。

利益がないかもしれない...最初に言ったように、設定をいじることで症状を変える方法を見つけることができるかもしれませんが、これは非常にヒットとミスであり、次回は助けにはなりません同じzend_mm_heap corruptedメッセージには、非常に多くの構成オプションしかありません。

バグを見つけたときにバグレポートを作成することは本当に重要です。バグを見つけた次の人がそれを行うとは考えられません...実際には、実際の解決策は決して神秘的ではありません。問題を認識している正しい人々。

USE_ZEND_ALLOC

環境でUSE_ZEND_ALLOC=0を設定すると、Zend独自のメモリマネージャーが無効になります。 Zendのメモリマネージャは、各リクエストが独自のヒープを持ち、リクエストの最後にすべてのメモリが解放されるようにし、PHPにちょうどよいサイズのメモリチャンクの割り当てに最適化されます。

これを無効にすると、これらの最適化が無効になります。さらに重要なことは、メモリリークが発生する可能性があることです。ZendMMに依存して、リクエストの最後にメモリを解放する拡張コードがたくさんあるためです(tut、tut)。

また、症状をhideすることもありますが、Zendのヒープとまったく同じ方法でシステムヒープが破損する可能性があります。

寛容であるか、寛容ではないように見えるかもしれませんが、問題の根本原因を修正しますそれはできません

それをまったく無効にする機能は、内部開発者の利益のためです。 Zend MMを無効にしてPHPをneverデプロイする必要があります。

41
Joe Watkins

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

export USE_ZEND_ALLOC=0
41
Hittz

unset()sを確認してください。デストラクタ内の$this(または同等のもの)へのunset()参照、およびデストラクタ内のunset()sが同じオブジェクトへの参照カウントを0に落とさないようにしてください。私はいくつかの研究を行ったが、それが通常ヒープの破損を引き起こすものであることがわかった。

破損したzend_mm_heapに関するPHPバグレポート エラーがあります。再現方法の例については、コメント[2011-08-31 07:49 UTC] f dot ardelian at gmail dot comをご覧ください。

私は、他のすべての「解決策」(php.iniの変更、少ないモジュールでソースからPHPをコンパイルするなど)が問題を隠すだけだと感じています。

22
f.ardelian

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

opcache.fast_shutdown=0

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

PHP 5.6をPHP-FPMおよびApache proxy_fcgiで使用していますが、それが重要な場合は...

7
Jesús Carrera

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

6
Piotr

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

5
Taco de Wolff

私はこの問題に1週間取り組んだ、これは私のために働いた、または少なくともそうであるようだ

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

3
sam

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

シーンに到着したとき、出力バッファリングはオフでした。出力のバッファリングを示唆するこのスレッドを読み取ることで、何が起こるかを確認するためにオン(= 4096)にしました。この時点で、それらはallエラーの表示を開始しました。これは、エラーが再現可能になったことで良かったです。

私は試し、拡張機能を無効にし始めました。その中でも、eaccellerator、pdo、ioncube loader、そして多くのlooked疑いがありましたが、助けにはなりませんでした。

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

そのメモでは、これは一般的なエラーメッセージであるように見えるので、これらの答えのすべてによってあなたの走行距離は異なります。

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

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

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

幸運を。

3
A.B. Carroll

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

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

2
Scott Davey

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

2
Vance Lucas

PHP 5.3では、多くの検索の後、これは私のために働いた解決策です:

このページの PHPガベージコレクションを無効化 を追加して、

<? gc_disable(); ?>

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

ソース

2
Kuf

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

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

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

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

2
Yarco

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

^^動作します! (?!)

2
hernanc

上記のすべてとzend.enable_gc = 0-唯一の構成設定を試してみました。

PHP 5.3.10-1ubuntu3.2 with Suhosin-Patch(cli)(built:Jun 13 2012 17:19:58)

2
Bethrezen

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

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

1
cedricliang

特性を使用していて、特性がクラスの後にロードされる場合(自動ロードの場合)、事前に特性をロードする必要があります。

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

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

1
srcspider

私にとっては、問題は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
broadband

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

1
Travis Derouin

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

1
Muto

多くの人がこの問題を解決するためにXDebugを無効にすることに言及しています。これは明らかに、多くの場合実行可能ではありません。理由は、コードをデバッグするためです。

同じ問題が発生し、IDE(PhpStorm 2019.1 EAP)でXDe​​bug接続のリッスンを停止すると、エラーが発生しなくなりました。

実際の修正は、既存のブレークポイントを削除することでした。

これが有効な修正である可能性は、PhpStormが、ファイルが外部的に変更された後(gitなど)に有効なコード行を参照しなくなったブレークポイントを削除するのが上手でない場合があることです

編集:xdebug課題トラッカーで対応するバグレポートを見つけました: https://bugs.xdebug.org/view.php?id=1647

0
Dejan Lukić

JessieにアップグレードされたDebianサーバーにzend_mm_heap corruptedとともにchild pid ... exit signal Segmentation faultがありました。長い調査の後、Zend-Engineが一般に利用可能になる前にXCacheがインストールされたことが判明しました。

apt-get remove php5-xcacheおよびservice Apache2 restartの後、エラーはなくなりました。

0
Martin Seitl

いくつかを助けるかもしれないいくつかのヒント

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
lexand

私はここで同じ状況にあり、上記の何も助けませんでしたが、もっと真剣にチェックすると問題が見つかりましたそして、単純な「return $ this-> redirect($ url)」を作成しませんでした。

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

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

私にとっては、XStorがPHPStormに組み込まれたRabbitMqだったため、[設定/言語とフレームワーク/ PHP /デバッグ/ Xdebug]> [外部接続を受け入れることができます]を選択解除しました。

0

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

0
Mikayla Maki

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

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

0
Structed

他の誰かが私と同じようにこの問題を抱えているという偶然の機会に、私は私のために働いた解決策を提供すると思いました。

システムドライブ以外のドライブのWindowsにphpがインストールされています(H:)。

Php.iniファイルでは、いくつかの異なるファイルシステム変数の値が\path\to\directoryのように記述されていました。これは、私のインストールがC:であった場合は正常に機能します。

値をH:\path\to\directoryに変更する必要がありました。ドライブ文字をphp.iniファイルのいくつかの異なる場所に追加すると、すぐに問題が修正されました。また、PEAR configの同じ問題を解決することも確認しました(これは必要ではないと思います)-いくつかの変数値がドライブ文字も除外しているためです。

0
dgo

2014年11月13日にPHPで修正されたバグがありました。

バグ#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バージョンに変更すると、問題はなくなりました。他の解決策はどれも役に立たなかったし、これは本当にセグメンテーション違反(500応答)を引き起こしていたため、opcacheを無効にしたり、エラーを抑制したくありませんでした。

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
0
ColinM

ここでの答えの多くは古いものです。私にとっては(ubuntu 14.04のOndrej SuryのPPA経由のphp 7.0.10and16.04)、問題はAPCにあるようです。私はapc_fetch()などを使用して数百の小さなビットのデータをキャッシュしていましたが、キャッシュのチャンクを無効にするとエラーが発生しました。回避策は、ファイルシステムベースのキャッシュに切り替えることでした。

Githubの詳細 https://github.com/oerdnj/deb.sury.org/issues/452#issuecomment-24547528 .

0
Steve

私にとって、PHPはmemcachedにセッション情報を保存するように設定されていたため、memcachedデーモンがクラッシュしました。それは100%のCPUを食べて、奇妙に振る舞っていました。 memcachedの再起動の問題がなくなった後。

0

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

);

私はあちこちで遊んでコードを忘れました-いくつかの場所でヒープが破損しました、いくつかのケースは単なるオールセグフォールトです:

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

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

0
dsomnus

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

0
Phillip Whelan

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

0
bkulyk

設定

assert.active = 0 

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

0
Vasiliy

サイレントエラーを見つけるために、コードを本当に探しましょう。 Symfonyアプリでは、twigベーステンプレートからブロックを削除した後、サブテンプレートで参照されていることを記憶していないため、zend_mm_heap破損エラーが発生しました。エラーはスローされませんでした。

0
hipnosis