1
0

More than 1 year has passed since last update.

[PHP] メモリの解放条件

Posted at

メモリとは

メモリとは、コンピュータにおいてプログラムやデータを記憶する装置のことである。
よく机に例えられて説明されることが多いが、そのメモリに不要なデータが解放されずに残り続けることによって、メモリオーバーのエラーになることがある。

その不要なメモリを解放するためについて、簡単に以下にまとめる。

この記事の参考資料↓

メモリが解放される条件(変数)

定義した変数のデータは、解放されない限りメモリに残り続ける。

◎解放される条件は以下の通り↓

  • 「実際のデータの参照が一つ無効になる」時、zvalの参照カウント(zvalのrefcount)を-1した結果、0であればデータはメモリから消滅する。
  • Garbage Collection Cycleの結果、参照カウントが0であれば、データはメモリから消滅する。

※詳しくは先ほどのリンクを参照!

まあ、定義した変数が全て使い終わったら…、というイメージで捉えておく。

1) 変数の有効範囲の消滅

変数の使用できる範囲から逃れる時、その有効範囲自体の消滅と同時に、変数は解放され、実際のデータの参照も無効になる。

function sampleFunc() {
    $local = 'a'; //$localは、function{}の範囲内で有効です。
}
sampleFunc(); // 関数の遂行が合わったあと、a関数内の$localは自動的に解除されます。

2) 明示的な変数シンボルの解除(unset)

phpでは、変数を明示的に開放できるunset()という関数がある。

unset(local) : void

3) 変数シンボルの参照再設定

変数シンボルの参照が再定義されると、以前の参照は無効になる。

$a = array(0);
$a = array(1); //この時、$aの変数の参照がarray(1)に上書きされ、array(0)に対する参照は無効になる。

メモリが解放されない条件

  • 「実際のデータの参照が一つ無効になる」時、参照カウント(refcount)が「1以上」であれば、データは消滅せずに残り続ける。

1) 同じスコープで、同じデータを参照する変数がある場合

同じ関数内などの同じスコープで、同じデータを参照する変数が複数存在する場合、一つの変数が解放されても、データは消滅しない。

$a = array(0);
$b = $a;

unset($a); 
var_dump($b); //$aの変数を解除しても、$bがarray(0)の参照を持っているため、消滅しない。 

2) 違うスコープで、同じデータを参照する変数がある場合

関数の引数として渡された場合などは、上位スコープでまだデータを参照しているため、現在のスコープから変数が解除されても、データは消えない。

function sampleFunc(object $obj) {
    unset($obj); 
    //現在のスコープの$objに対する参照は解放される。
    //しかし、上位スコープにいる$aの変数の参照がまだ有効なため、データは消滅しない。
}

$a = array(0); // このarray(0)は残っている。
sampleFunc($a);

3) compound typeの変数の内部で、同じデータを参照する変数がある場合

array, objectなどのcompound typeは、内部にデータは参照を持つことができる。
その内部でデータを参照していると、データは消滅しません。

function x(object $obj) {
    $data = array(0); 

    $obj->data = $data;
    //$dataは、x関数の遂行後に解除されますが、stdClassのインスタンスのメンバーとして、array(0)データを参照することになり、データは消滅しません。
}
$a = new \stdClass;
x($a);

最後に

メモリの概念を理解することで、効率よくデータを扱えそうなので、勉強していきたい。
また、メモリリーク、ガベージコレクションについての記事もまとめる。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0