web-dev-qa-db-ja.com

致命的なエラー:134217728バイトの許容メモリサイズが使い果たされました(CodeIgniter + XML-RPC)

私は定期的に新しい販売データを1つの集中型データベースに送信する多数のPOSシステムを持っています。

クライアントPOSはPHPPOSをベースにしており、私は販売データをサービスに送信するために標準のXML-RPCライブラリを使用するモジュールを実装しました。サーバーシステムはCodeIgniter上に構築されており、WebサービスコンポーネントにXML-RPCおよびXML-RPCSライブラリを使用します。大量の販売データ(salesテーブルから50行、sales_itemsから販売内の各商品に関連する行)を送信するたびに、次のエラーが発生します。

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes)

128Mはphp.iniのデフォルト値ですが、私はそれが破るべき巨大な数であると思います。実際、私はこの値を1024Mに設定しようとさえしました、そしてそれがするすべてはエラーを出すのにより長い時間がかかることです。

私が取ったステップに関しては、私はサーバー側のすべての処理を無効にしようとしました、そしてそれは入力に関係なく缶詰の応答を返すようにそれを装備しました。しかし、問題は実際のデータ送信にあると思います。私はPHPの最大スクリプト実行時間を無効にしようとさえしましたが、それでもエラーになります。

555
ArcticZero

ini_set('memory_limit', '-1');によるmemory_limitの変更は not 適切な解決策です。しないでください。

あなたのPHPコードはどこかにメモリリークがあるかもしれません、そしてあなたはそれが望むすべてのメモリを使うようにサーバに言っています。あなたはまったく問題を解決しなかったでしょう。サーバーを監視している場合は、おそらくRAMの大部分を使い果たし、さらにはディスクにスワップしていることがわかります。

あなたはおそらくあなたのコードの中の問題のあるコードを突き止めてそれを修正しようとするべきです。

655
Jeff

ini_set('memory_limit', '-1');はデフォルトの PHPメモリ制限 を上書きします。

200
Chris Lane

正しい方法はあなたのphp.iniファイルを編集することです。 memory_limitをあなたの望む値に編集してください。

あなたの質問からして、128M(これはデフォルトの制限です)を超えています。それほど多くはかかりませんので、あなたのコードには重大な問題があります。

なぜそれがそんなにかかるのかを知っていて、memory_limit = 512M以上に設定したいのなら、あなたは良いはずです。

122
Basav

PHPのメモリ割り当ては、恒久的または一時的に調整できます。

恒久的に

PHPメモリの割り当ては、2通りの方法で恒久的に変更できます。

php.iniファイルにアクセスできる場合は、memory_limitの値を希望の値に編集できます。

あなたがあなたのphp.iniファイルにアクセスできない(そしてあなたのウェブホストがそれを許可する)場合、あなたはあなたの.htaccessファイルを通してメモリ割り当てを上書きすることができます。 php_value memory_limit 128Mを追加します(または、あなたが望む割り当てであれば何でも)。

一時的

PHPファイル内からメモリ割り当てをその場で調整できます。あなたは単にini_set('memory_limit', '128M');というコードを持っています。値を "-1"に設定すると、メモリ制限を削除できます(ただし、マシン制限またはインスタンス制限は適用される場合があります)。

88
Umair Idrees

PHPスクリプトでメモリリークが発生するのは非常に簡単です。特にORMなどの抽象化を使用する場合は特にそうです。 Xdebugを使用してスクリプトをプロファイルし、そのメモリがどこにいったのかを調べてください。

59
troelskn

Array_Pushを使って2250万レコードを配列に追加したとき、php.iniのメモリ制限として4Gを使用して、約20Mレコードで "メモリを使い果たした"致命的なエラーが発生し続けました。これを修正するために、私は文を追加しました

$old = ini_set('memory_limit', '8192M'); 

ファイルの先頭にあります。今、すべてがうまくいっています。私はphpにメモリリークがあるかどうか、それが私の仕事ではないかどうかも知りませんし、気にしません。仕事を終わらせるだけでいいのです。

プログラムはとても簡単です。

$fh = fopen($myfile);
while (!feof($fh)) {
      array_Push($file, stripslashes(fgets($fh)));
}  
fclose($fh);

致命的なエラーは、iがメモリ制限を引き上げるまで3行目を指しています。

52
JamesAD-0

memory_limitphp.iniを設定し、phpinfo()を使用して値を正しく読み取っても、このエラーが発生し続けました。

これを変更することで:

memory_limit=4G

これに:

memory_limit=4096M

これはPHP 7の問題を修正しました。

45
Danny Beckett

上記のエラーが表示されたとき - 特に(tried to allocate __ bytes)が低い値の場合、それは、逃げることなく自分自身を呼び出す関数のように、無限ループの指標となる可能性があります。

function exhaustYourBytes()
{
    return exhaustYourBytes();
}
21
Kristen Waite

これら2行を有効にした後。
働き始めました

; Determines the size of the realpath cache to be used by PHP. This value should
; be increased on systems where PHP opens many files to reflect the quantity of
; the file operations performed.
; http://php.net/realpath-cache-size
realpath_cache_size = 16k

; Duration of time, in seconds for which to cache realpath information for a given
; file or directory. For systems with rarely changing files, consider increasing this
; value.
; http://php.net/realpath-cache-ttl
realpath_cache_ttl = 120

18

Fastcgi/fpmのmemory_limitを変更することでこれを正しく修正できます。

$vim /etc/php5/fpm/php.ini

128から512のようにメモリを変更してください下記参照

; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = 128M

; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = 512M
17
Derick Fynn

あなたのサイトのルートディレクトリ: -

ini_set('memory_limit', '1024M');
15
Gaurang P

memory_limitファイルのphp.ini値を変更するのではなく、大量のメモリを使用する可能性があるコード部分がある場合は、そのセクションを実行する前にmemory_limitを削除してから置き換えます。

$limit = ini_get('memory_limit');
ini_set('memory_limit', -1);
// ... do heavy stuff
ini_set('memory_limit', $limit);
12
mykeels

Drupalの7では、あなたはあなたのサイト/既定のフォルダにあるのsettings.phpファイルにメモリ制限を変更することができます。ライン260の周りに、あなたはこれを参照してくださいよ。

ini_set('memory_limit', '128M');

あなたのphp.iniの設定が十分に高い場合であっても、これはあなたのDrupalのsettings.phpファイルに設定されていない場合は、128メガバイト以上を消費することはできません。

11
LK7889

Drupalユーザーにとって、このChris Laneの答えは:

ini_set('memory_limit', '-1');

動作しますが、開始直後に配置する必要があります

<?php

サイトのルートディレクトリにあるindex.phpファイルにタグを付けます。

11
sigmapi13

メモリ制限を php.ini fileから変更してApacheを再起動します。再起動後、 phpinfo()を実行してください。 memory_limit変更確認のための任意のphpファイルからの関数。

memory_limit = -1

メモリ制限-1は、現在メモリ制限が設定されていないことを意味します。

10
Hasib Kamal

PHP 5.3以降では、.user.iniファイルをpublic_htmlフォルダーに置くことでメモリー制限を変更できます。上記のファイルを作成して、その中に次の行を入力するだけです。

memory_limit = 64M

一部のcPanelホストはこのメソッドのみを受け入れます。

7
Sabi

地球上でこの小さな関数がなぜメモリリークを引き起こすのかを調べるために自分の髪の毛を傷つけている人のために、時々ちょっとした間違いで、関数は永遠にそれ自身を再帰的に呼び出し始めます。

例えば、それを代行しようとしているオブジェクトの機能と同じ名前を持つProxy Class。

class Proxy {

    private $actualObject;

    public function doSomething() {

        return $this->actualObjec->doSomething();
    }
}   

実際には、その少しactualObjecメンバーを持ってくるのを忘れるかもしれません、そして、Proxyが実際にそのdo​​Somethingメソッドを持っているので、PHPはあなたにエラーを与えないでしょう。なぜそれがメモリをリークしているのかを調べるために数分のうちに。

7
madz

クラッシュページ? enter image description here

(MySQLが大きな行をクエリしなければならないときに起こります。デフォルトではmomory_limitはsmallに設定されています。これはハードウェアにとって安全でした)

php.iniを増やす前に、システムの既存のメモリ状態を確認できます。

# free -m
             total       used       free     shared    buffers     cached
Mem:         64457      63791        666          0       1118      18273
-/+ buffers/cache:      44398      20058
Swap:         1021          0       1021

ここで私は次のようにそれを増やしてから、クラッシュページの問題を修正するためにservice httpd restartを使っています。

# grep memory_limit /etc/php.ini
memory_limit = 512M
6
YumYumYum

以前の作業よりも小さいデータセットを実行しているときに、以下のエラーが発生しました。

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes) in C:\\workspace\image_management.php on line 173

障害の検索がここに私をもたらしたので私はそれが常に上記の技術的な解決策ではなく、もっと単純なものであることに言及したいと思いました。私の場合はFirefoxでした。プログラムを実行する前は、すでに1,157 Mを使用していました。
私が数日の間に一度に少しずつ50分のビデオを見ていたことがわかり、それが物を台無しにしました。それは熟考することさえもせずに専門家が修正するような種類の修正ですが、私のような人にとっては注意する必要があります。

4
M61Vulcan

WHM搭載のVPS(Virtual Private Server)を使用している場合は、PHP.INIを直接編集する権限がないことがわかります。システムはそれをしなければならない。 WHM Hostコントロールパネルで、Service Configuration> PHP Configuration Editorに移動し、memory_limitを変更します。

Updating memory_limit on WHM 11.48.4

3
Janckos

このようにスクリプトを実行すると(例えばcronの場合)、php5 /pathToScript/info.phpと同じエラーが発生します。

正しい方法はphp5 -cli /pathToScript/info.php

3
ratm

次のものを含めるときや必要とするときに便利です。
dbconnection.php 、実際に処理されるファイル内の_functions.php
ヘッダーに含めるのではなくそれ自体が含まれています。

もしあなたの header footer が含まれているのであれば、headerが含まれる前にあなたの全ての機能ファイルを含めてください。

3
Kerim

このエラーは、例外処理やその他の操作を伴う再帰を引き起こすPHPコードのバグが原因で発生する場合があります。残念ながら、私は小さな例を作成することができませんでした。

私のために何度か起こったこれらのケースでは、set_time_limitが失敗し、ブラウザは無限ループまたは致命的なエラーメッセージでPHP出力をロードしようとし続けます。この質問のトピック。

追加することで許可される割り当てサイズを減らす

ini_set('memory_limit','1M');

コードの先頭近くで、致命的なエラーを防ぐことができるはずです。

その後、終了するプログラムが残っている可能性がありますが、デバッグは依然として困難です。

この時点で、プログラム内にBreakLoop()呼び出しを挿入して制御を取得し、プログラムのどのループまたは再帰が問題を引き起こしているかを見つけます。

BreakLoopの定義は次のとおりです。

function BreakLoop($MaxRepetitions=500,$LoopSite="unspecified")
    {
    static $Sites=[];
    if ([email protected]$Sites[$LoopSite] || !$MaxRepetitions)
        $Sites[$LoopSite]=['n'=>0, 'if'=>0];
    if (!$MaxRepetitions)
        return;
    if (++$Sites[$LoopSite]['n'] >= $MaxRepetitions)
        {
        $S=debug_backtrace(); // array_reverse
        $info=$S[0];
        $File=$info['file'];
        $Line=$info['line'];
        exit("*** Loop for site $LoopSite was interrupted after $MaxRepetitions repetitions. In file $File at line $Line.");
        }
    } // BreakLoop

$ LoopSite引数には、コード内の関数の名前を指定できます。表示されるエラーメッセージはBreakLoop()呼び出しを含む行を指すため、実際には必要ありません。

1
David Spector

私の場合、それは関数が書かれた方法に関する短い問題でした。メモリリークは、関数の入力変数に新しい値を代入することによって引き起こされる可能性があります。

/**
* Memory leak function that illustrates unintentional bad code
* @param $variable - input function that will be assigned new value
* @return null
**/
function doSomehting($variable){
    $variable = 'set value';
    // or
    $variable .= 'set value';
}
1

yieldを使うことも解決策かもしれません https://www.php.net/manual/en/language.generators.syntax.php

より大きなメモリストレージ用にPHP.iniファイルを変更する代わりに、ループ内にyieldを実装すると問題が解決する場合があります。すべてのデータを一度にダンプするのではなく、大量のメモリ使用量を節約しながら1つずつ読み取ることができます。

0
LukeDS

Ini_set( 'memory_limit'、 '-1')を追加するだけです。あなたのWebページの一番上に行を入れます。そしてあなたは-1から16Mなどの場所であなたの必要性に従ってあなたの記憶を設定することができます。

0