PHPカーネル研究静的変数
せいてきへんすう
これは静的グローバル変数であってもよく、unsetを呼び出さないと、プログラムが終了するまでZendメモリ管理によって解放されません.
これは静的ローカル変数です:関数で定義され、関数が実行された後、静的変数は消えません.
静的メンバー変数:クラスで定義され、すべてのクラスのオブジェクトで共有できます.
たとえば
最後に$a=4になりました..
カーネルから分析します
staticは関数ではなくキーワードなのでLEX構文解析からしか検索できません
zend/zend_を開くlanguage_scanner.l staticの検索
コードの検索
マクロ再オープンzend/zend_language_pareser.l検索T_STATIC検出コード
static_にフォローvar_リスト検索コード
ここだよ..PHPの構文解析プログラムから上のコードzend_に解析されますdo_fetch_static_variableという関数はzend/zend_にありますcompile.cで定義するコードは以下の通りです.
これは静的グローバル変数であってもよく、unsetを呼び出さないと、プログラムが終了するまでZendメモリ管理によって解放されません.
これは静的ローカル変数です:関数で定義され、関数が実行された後、静的変数は消えません.
静的メンバー変数:クラスで定義され、すべてのクラスのオブジェクトで共有できます.
たとえば
- <?php
-
- function test(){
-
- static $a=1;
-
- $a++;
-
- }
-
- test(); //$a=2
-
- test();//$a=3
-
- test();//$a=4
最後に$a=4になりました..
カーネルから分析します
staticは関数ではなくキーワードなのでLEX構文解析からしか検索できません
zend/zend_を開くlanguage_scanner.l staticの検索
コードの検索
- <ST_IN_SCRIPTING>"static" {
- return T_STATIC;
- }
マクロ再オープンzend/zend_language_pareser.l検索T_STATIC検出コード
- T_STATIC static_var_list ';'
static_にフォローvar_リスト検索コード
- static_var_list:
- static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
- | static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); }
- | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); }
- | T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); }
-
- ;
ここだよ..PHPの構文解析プログラムから上のコードzend_に解析されますdo_fetch_static_variableという関数はzend/zend_にありますcompile.cで定義するコードは以下の通りです.
- void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC)
- {
- zval *tmp; //
- zend_op *opline;
- znode lval;
- znode result;
-
- ALLOC_ZVAL(tmp); //
-
- if (static_assignment) {
- *tmp = static_assignment->u.constant;
- } else {
- INIT_ZVAL(*tmp);
- }
- if (!CG(active_op_array)->static_variables) {// HASH
- ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
- // HASH
- zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
- }
- zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL);
-
- if (varname->op_type == IS_CONST) {
- if (Z_TYPE(varname->u.constant) != IS_STRING) {
- convert_to_string(&varname->u.constant);
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->result.op_type = IS_VAR;
- opline->result.u.EA.type = 0;
- opline->result.u.var = get_temporary_variable(CG(active_op_array));
- opline->op1 = *varname;
- SET_UNUSED(opline->op2);
- opline->op2.u.EA.type = ZEND_FETCH_STATIC;
- result = opline->result;
-
- if (varname->op_type == IS_CONST) {
- zval_copy_ctor(&varname->u.constant);
- }
- fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
-
- if (fetch_type == ZEND_FETCH_LEXICAL) {
- znode dummy;
-
- zend_do_begin_variable_parse(TSRMLS_C);
- zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
- zend_do_free(&dummy TSRMLS_CC);
- } else {
- zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
- }
- CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
-
- /* zval_dtor(&varname->u.constant); */
- }