PHPで変数に値をセットしたときの内部的な挙動を見る

下記のようなコードを実行したときに、PHP内部(C言語レベル)でどういう動きになっているのか見てみました。
$x="hello";

結論

php -r '$x="hello";'
PHP 5.4.14で上記コードを実行したとき、呼び出しシーケンスは下記のようになります。
ファイル名:行番号   関数名 (引数)
sapi/cli/php_cli.c:1364      main (argc=3, argv=0xbfa6cf94)
↓
sapi/cli/php_cli.c:1028      do_cli (argc=3, argv=0xbfa6cf94)
↓
Zend/zend_execute_API.c:1257 zend_eval_string_ex (str=0xbfa6db98 "$x=\"hello\"; echo $x;", retval_ptr=0x0, string_name=0x83ace6c "Command line code", handle_exceptions=1)
↓
Zend/zend_execute_API.c:1246 zend_eval_stringl_ex (str=0xbfa6db98 "$x=\"hello\"; echo $x;", str_len=20, retval_ptr=0x0, string_name=0x83ace6c "Command line code", handle_exceptions=1)
↓
Zend/zend_execute_API.c:1199 zend_eval_stringl (str=0xbfa6db98 "$x=\"hello\"; echo $x;", str_len=20, retval_ptr=0x0, string_name=0x83ace6c "Command line code")
↓
Zend/zend_vm_execute.h:410   execute (op_array=0xb765f344)
↓
Zend/zend_vm_execute.h:29177 ZEND_ASSIGN_SPEC_CV_CONST_HANDLER (execute_data=0xb7644074)
↓
Zend/zend_execute.c:865      zend_assign_const_to_variable (variable_ptr_ptr=0xb765ff8c, value=0xb7660068)

調査方法

gdbでPHPを起動して、main関数にブレークポイントをしかけて、後はひたすら1行ずつステップ実行して処理を追っていきました。
gdb  sapi/cli/php
(gdb) break main
(gdb) run -r '$x="hello"; echo $x;'
(gdb) step
(gdb) step
このstepを延々と続けたところそれっぽいコードに行きついたので、おもむろにbacktrace。
(gdb) backtrace
#0  zend_assign_const_to_variable (variable_ptr_ptr=0xb765ff8c, value=0xb7660068) at /home/dqneo/src/php-5.4.14/Zend/zend_execute.c:865
#1  0x082aa24c in ZEND_ASSIGN_SPEC_CV_CONST_HANDLER (execute_data=0xb7644074) at /home/dqneo/src/php-5.4.14/Zend/zend_vm_execute.h:29177
#2  0x0825c2e4 in execute (op_array=0xb765f344) at /home/dqneo/src/php-5.4.14/Zend/zend_vm_execute.h:410
#3  0x0821c1df in zend_eval_stringl (str=0xbfa6db98 "$x=\"hello\"; echo $x;", str_len=20, retval_ptr=0x0, string_name=0x83ace6c "Command line code") at /home/dqneo/src/php-5.4.14/Zend/zend_execute_API.c:1199
#4  0x0821c42a in zend_eval_stringl_ex (str=0xbfa6db98 "$x=\"hello\"; echo $x;", str_len=20, retval_ptr=0x0, string_name=0x83ace6c "Command line code", handle_exceptions=1)
    at /home/dqneo/src/php-5.4.14/Zend/zend_execute_API.c:1246
#5  0x0821c494 in zend_eval_string_ex (str=0xbfa6db98 "$x=\"hello\"; echo $x;", retval_ptr=0x0, string_name=0x83ace6c "Command line code", handle_exceptions=1)
    at /home/dqneo/src/php-5.4.14/Zend/zend_execute_API.c:1257
#6  0x082bfeb3 in do_cli (argc=3, argv=0xbfa6cf94) at /home/dqneo/src/php-5.4.14/sapi/cli/php_cli.c:1028
#7  0x082c0ddc in main (argc=3, argv=0xbfa6cf94) at /home/dqneo/src/php-5.4.14/sapi/cli/php_cli.c:1364

VM(Virtual Machine)やopcodeまわりは予備知識がないと何がどうなっているのかさっぱりわかりませんね。。。
おいおい勉強していきたいと思います。
カテゴリ:

人気記事