PHP内核研究 静态变量

原创
2016-06-13 10:54:43 829浏览

静态变量

它可以是 静态全局变量,如果不调用unset,那么这个静态变量会一直存在,直到程序退出时才由Zend内存管理来释放

它可以是 静态局部变量:在函数里定义,函数执行完后,该静态变量不会消失

它可以是 静态成员变量:在类里定义,它可以在所有类的对象中共享

例如

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

找到代码

"static" {

return T_STATIC;

}

是一个宏

再打开 zend/zend_language_pareser.l

搜 T_STATIC

找到代码

T_STATIC static_var_list ';'

跟进 static_var_list

找到代码

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 */ www.2cto.com

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); */

}

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。