突然、これまでにないアプリケーションで問題が発生しました。 Apacheのエラーログを確認することにしましたが、「zend_mm_heapが破損しています」というエラーメッセージが見つかりました。これは何を意味するのでしょうか。
OS:Fedora Core 8 Apache:2.2.9 PHP:5.2.6
多くの試行錯誤の後、php.iniファイルのoutput_buffering
値を増やすと、このエラーがなくなることがわかりました。
PHP 5.5で同じエラーが発生し、出力バッファリングを増やしても解決しませんでした。私もAPCを実行していなかったので、それは問題ではありませんでした。最終的にopcacheに追跡しました。CLIから無効にする必要がありました。これには特定の設定がありました:
opcache.enable_cli=0
切り替えると、zend_mm_heap破損エラーはなくなりました。
これは、構成オプションを変更することで必ずしも解決できる問題ではありません。
構成オプションを変更すると、良い結果が得られる場合がありますが、状況を悪化させるか、まったく何もしないことがあります。
エラーの性質は次のとおりです。
#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でデバッグできる問題ではなく、内部開発者の注意が絶対に必要です。
アクションのコースは次のとおりです。
利益がないかもしれない...最初に言ったように、設定をいじることで症状を変える方法を見つけることができるかもしれませんが、これは非常にヒットとミスであり、次回は助けにはなりません同じzend_mm_heap corrupted
メッセージには、非常に多くの構成オプションしかありません。
バグを見つけたときにバグレポートを作成することは本当に重要です。バグを見つけた次の人がそれを行うとは考えられません...実際には、実際の解決策は決して神秘的ではありません。問題を認識している正しい人々。
環境でUSE_ZEND_ALLOC=0
を設定すると、Zend独自のメモリマネージャーが無効になります。 Zendのメモリマネージャは、各リクエストが独自のヒープを持ち、リクエストの最後にすべてのメモリが解放されるようにし、PHPにちょうどよいサイズのメモリチャンクの割り当てに最適化されます。
これを無効にすると、これらの最適化が無効になります。さらに重要なことは、メモリリークが発生する可能性があることです。ZendMMに依存して、リクエストの最後にメモリを解放する拡張コードがたくさんあるためです(tut、tut)。
また、症状をhideすることもありますが、Zendのヒープとまったく同じ方法でシステムヒープが破損する可能性があります。
寛容であるか、寛容ではないように見えるかもしれませんが、問題の根本原因を修正しますそれはできません。
それをまったく無効にする機能は、内部開発者の利益のためです。 Zend MMを無効にしてPHPをneverデプロイする必要があります。
Linuxボックスを使用している場合は、コマンドラインでこれを試してください。
export USE_ZEND_ALLOC=0
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をコンパイルするなど)が問題を隠すだけだと感じています。
私にとっては、試してみるまで、以前の答えはどれもうまくいきませんでした:
opcache.fast_shutdown=0
これまでのところうまくいくようです。
PHP 5.6をPHP-FPMおよびApache proxy_fcgiで使用していますが、それが重要な場合は...
私の場合、このエラーの原因は配列の1つが非常に大きくなっていたことです。スクリプトを設定して、反復ごとに配列をリセットし、問題をソートしました。
バグトラッカーに従って、opcache.fast_shutdown=0
を設定します。高速シャットダウンでは、Zendメモリマネージャーを使用して混乱をクリーンアップします。これにより、これが無効になります。
私はこの問題に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秒かかっていました。このテストは何度も実行しましたが、毎回同じテストを実行しました。毎回新しいオブジェクトを作成する代わりに(ここには長いループがあります)、オブジェクトを再利用する必要があると考えました。これまでにスクリプトを十数回テストしましたが、メモリエラーはなくなりました。
ここに答えが1つあるとは思わないので、私の経験を追加します。ランダムなhttpd segfaultsとともにこの同じエラーを見ました。これはcPanelサーバーでした。問題の症状は、Apacheがランダムに接続をリセットすることでした(Chromeでデータが受信されないか、Firefoxで接続がリセットされました)。これらは一見ランダムに見えました。ほとんどの場合は動作し、時には動作しませんでした。
シーンに到着したとき、出力バッファリングはオフでした。出力のバッファリングを示唆するこのスレッドを読み取ることで、何が起こるかを確認するためにオン(= 4096)にしました。この時点で、それらはallエラーの表示を開始しました。これは、エラーが再現可能になったことで良かったです。
私は試し、拡張機能を無効にし始めました。その中でも、eaccellerator、pdo、ioncube loader、そして多くのlooked疑いがありましたが、助けにはなりませんでした。
私はついに「homeloader.so」としていたずらなPHP拡張モジュールを見つけました。これはcPanel-easy-installerモジュールのようなものです。削除後、他の問題は発生していません。
そのメモでは、これは一般的なエラーメッセージであるように見えるので、これらの答えのすべてによってあなたの走行距離は異なります。
上記のすべてに失敗した場合、次のようなことを試すこともできます。
幸運を。
バッファリングを使用するモジュールを探し、選択的に無効にします。
CentOS 4.8でPHP 5.3.5を実行していますが、これを行った後、eacceleratorにアップグレードが必要であることがわかりました。
所有しているサーバーでもこの問題が発生しましたが、根本的な原因はAPCでした。 php.iniファイルの「apc.so」拡張子をコメントアウトし、Apacheをリロードすると、サイトがすぐに復旧しました。
PHP 5.3では、多くの検索の後、これは私のために働いた解決策です:
このページの PHPガベージコレクションを無効化 を追加して、
<? gc_disable(); ?>
問題のあるページの最後まで、すべてのエラーが消えました。
ソース 。
多くの理由がこの問題を引き起こす可能性があると思います。そして、私の場合、私は2つのクラスに同じ名前を付け、別のものをロードしようとします。
class A {} // in file a.php
class A // in file b.php
{
public function foo() { // load a.php }
}
そして、それは私の場合この問題を引き起こします。
(laravelフレームワークを使用して、実際にphp artisan db:seedを実行します)
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'));
^^動作します! (?!)
上記のすべてとzend.enable_gc = 0
-唯一の構成設定を試してみました。
PHP 5.3.10-1ubuntu3.2 with Suhosin-Patch(cli)(built:Jun 13 2012 17:19:58)
私はPHP拡張機能を書いていますが、この問題も発生しています。拡張機能から複雑なパラメータを使用してextern関数を呼び出すと、このエラーがポップアップします。
その理由は、extern関数のパラメーター(char *)にメモリを割り当てていないからです。同じ種類の拡張機能を作成している場合は、これに注意してください。
特性を使用していて、特性がクラスの後にロードされる場合(自動ロードの場合)、事前に特性をロードする必要があります。
https://bugs.php.net/bug.php?id=62339
注:このバグは非常にランダムです。その性質のため。
私にとっては、問題は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)
これと同じ問題があり、memcachedセッションのsession.save_pathのIPが間違っていました。正しいIPに変更すると、問題が修正されました。
「zend_mm_heap破損」は、メモリ管理の問題を意味します。 PHPモジュールが原因である可能性があります。私の場合、APCのインストールはうまくいきました。理論的には、eAccelerator、XDebugなどのような他のパッケージも役立ちます。または、そのようなモジュールがインストールされている場合は、それらのスイッチをオフにしてみてください。
多くの人がこの問題を解決するためにXDebugを無効にすることに言及しています。これは明らかに、多くの場合実行可能ではありません。理由は、コードをデバッグするためです。
同じ問題が発生し、IDE(PhpStorm 2019.1 EAP)でXDebug接続のリッスンを停止すると、エラーが発生しなくなりました。
実際の修正は、既存のブレークポイントを削除することでした。
これが有効な修正である可能性は、PhpStormが、ファイルが外部的に変更された後(gitなど)に有効なコード行を参照しなくなったブレークポイントを削除するのが上手でない場合があることです
編集:xdebug課題トラッカーで対応するバグレポートを見つけました: https://bugs.xdebug.org/view.php?id=1647
JessieにアップグレードされたDebianサーバーにzend_mm_heap corrupted
とともにchild pid ... exit signal Segmentation fault
がありました。長い調査の後、Zend-Engineが一般に利用可能になる前にXCacheがインストールされたことが判明しました。
apt-get remove php5-xcache
およびservice Apache2 restart
の後、エラーはなくなりました。
いくつかを助けるかもしれないいくつかのヒント
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番目の場所です。
私はここで同じ状況にあり、上記の何も助けませんでしたが、もっと真剣にチェックすると問題が見つかりましたそして、単純な「return $ this-> redirect($ url)」を作成しませんでした。
井戸を再発明しようとして、これが問題でした。
この関連が誰かを助けることを願っています!
私にとっては、XStorがPHPStormに組み込まれたRabbitMqだったため、[設定/言語とフレームワーク/ PHP /デバッグ/ Xdebug]> [外部接続を受け入れることができます]を選択解除しました。
他の答えのどれもそれに対処しなかったので、誤って無限ループを実行したときにphp 5.4でこの問題が発生しました。
私にとって、メモリリークを引き起こし、MemoryManagerをクラッシュさせたのはZendDebuggerでした。
私はそれを無効にし、現在新しいバージョンを探しています。見つからない場合は、xdebugに切り替えます...
他の誰かが私と同じようにこの問題を抱えているという偶然の機会に、私は私のために働いた解決策を提供すると思いました。
システムドライブ以外のドライブのWindowsにphp
がインストールされています(H:)。
Php.iniファイルでは、いくつかの異なるファイルシステム変数の値が\path\to\directory
のように記述されていました。これは、私のインストールがC:
であった場合は正常に機能します。
値をH:\path\to\directory
に変更する必要がありました。ドライブ文字をphp.ini
ファイルのいくつかの異なる場所に追加すると、すぐに問題が修正されました。また、PEAR config
の同じ問題を解決することも確認しました(これは必要ではないと思います)-いくつかの変数値がドライブ文字も除外しているためです。
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
ここでの答えの多くは古いものです。私にとっては(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 .
私にとって、PHPはmemcachedにセッション情報を保存するように設定されていたため、memcachedデーモンがクラッシュしました。それは100%のCPUを食べて、奇妙に振る舞っていました。 memcachedの再起動の問題がなくなった後。
私の場合、コードで次のことを忘れました:
);
私はあちこちで遊んでコードを忘れました-いくつかの場所でヒープが破損しました、いくつかのケースは単なるオールセグフォールトです:
[2011年6月8日17:23:21] [通知]子pid 5720終了信号セグメンテーションエラー(11)
Mac 10.6.7とxamppを使用しています。
PHP 5.2+で実行中に '&'を使用して明示的に参照を強制する古いコードを実行すると、このエラーとSIGSEGVにも気付きました。
これに対する解決策を見つけられなかったため、LAMP環境をアップグレードすることにしました。 PHP 5.3.xでUbuntu 10.4 LTSに行きました。これは私にとって問題を止めたようです。
設定
assert.active = 0
php.iniで助けてくれました(php5UTF8
ライブラリの型アサーションをオフにし、zend_mm_heap corrupted
がなくなりました)
サイレントエラーを見つけるために、コードを本当に探しましょう。 Symfonyアプリでは、twigベーステンプレートからブロックを削除した後、サブテンプレートで参照されていることを記憶していないため、zend_mm_heap破損エラーが発生しました。エラーはスローされませんでした。