PHPのメモリ管理について(参照渡し)

このエントリーをはてなブックマークに追加

notoです。

前回のPHPメモリ管理(値渡し)に引き続き、今回は参照渡しの検証になります。


 

参照渡し

$a = &$bとすることで、PHPでは参照渡しになります。
その際にPHPのメモリ管理はどう行われているかを確認していきます。

 

基本的な参照渡し

サンプルコードです。

<?php
$hoge = 'ほげ';
$piyo = &$hoge;

xdebug_debug_zval('hoge');
xdebug_debug_zval('piyo');

 

実行結果

hoge: (refcount=2, is_ref=1)='ほげ'
piyo: (refcount=2, is_ref=1)='ほげ'

 
シンボルテーブル

変数名 zval No
hoge #0001
piyo #0001

 
zval

No Value refcount is_ref
#0001 ほげ 2 1

 

is_refというのは参照されているかいないかのbool値です。
値渡しの場合はis_refの値は「0」がセットされ、参照渡しの場合は、「1」がセットされます。

 

参照渡し後、値を代入

参照で代入後、異なる値を代入します。

サンプルコード

<?php
$hoge = 'ほげ';
$piyo = &$hoge;

$piyo = 'ぴよ';

xdebug_debug_zval('hoge');
xdebug_debug_zval('piyo');

 

実行結果

hoge: (refcount=2, is_ref=1)='ぴよ'
piyo: (refcount=2, is_ref=1)='ぴよ'

 
図は省略しますが、変数hoge 変数piyoともに同じzvalコンテナにリンクされている為、変数piyoに値を代入したことで、同じzvalコンテナに新しい値が書きこまれたのが確認できます。

 

参照渡し後、unset

参照で代入後、一方をunsetします。

サンプルコード

<?php
$hoge = 'ほげ';
$piyo = &$hoge;

unset($piyo);

xdebug_debug_zval('hoge');
xdebug_debug_zval('piyo');

 

実行結果

hoge: (refcount=1, is_ref=0)='ほげ'

 

シンボルテーブル

変数名 zval No
hoge #0001

 
zval

No Value refcount is_ref
#0001 ほげ 1 0

 

unsetで、zvalコンテナに書き込まれた値はすべて解放されると思いきや違います。

unsetはzvalコンテナとシンボルテーブルのリンクの解除を行うだけです。unsetを行うことでシンボルテーブルのリンクが1つ解除され、refcount=2だったものがrefcount=1と参照カウントが減っています。

refcountが0となった時点で、メモリが解放される仕組みとなっています。PHPはこのようにガベージコレクションにリファレンスカウンタ方式を利用してメモリを管理しています。

また配列やobjectのような複合型は、複雑なので書かないです。。。
もちろんPHPのマニュアルには記載してありますよ。

参考元:
参照カウント法
「はじめに-PHP変数管理解説(1)-参照と値渡しの明確な理解のために」

return top