117 views

经典网络编程教学之在PHP浏览器内核探讨静态变量

By | 2019年3月3日

静态变量

它可以是静态全局变量。如果未调用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_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 */

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

本文转载于:http://win-man.com
本文关键词:高防CDN 防DDoS攻击 防CC攻击 高防服务器
作者:云漫网络技术人员

发表评论

电子邮件地址不会被公开。 必填项已用*标注