PHP内核研究 静态变量
静态变量
它可以是 静态全局变量,如果不调用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); */
- }
PHP内核研究 静态变量的更多相关文章
- 深入理解PHP内核(九)变量及数据类型-静态变量
原文链接:http://www.orlion.ga/251/ 通常静态变量是静态分配的,他们的生命周期和程序的生命周期一样长,只有在程序退出后才结束生命周期,这和局部变量相反,有的语言中全局变量也是静 ...
- [转]Android静态变量的生命周期
原文地址:https://my.oschina.net/jerikc/blog/137207 Android是用Java开发,其静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的 ...
- 深入了解C#中的静态变量和静态构造函数
深入的剖析C#中静态变量和静态构造函数: 在日常的程序开发过程经常会使用到静态变量,众所周知,静态变量时常驻内存的变量,它的生命周期是从初始化开始一直到Application结束.但是,我们经常会忽略 ...
- PHP内核探索之变量(7)- 不平凡的字符串
切,一个字符串有什么好研究的. 别这么说,看过<平凡的世界>么,平凡的字符串也可以有不平凡的故事.试看: (1) 在C语言中,strlen计算字符串的时间复杂度是?PHP中呢? ...
- PHP内核探索之变量(4)- 数组操作
上一节(PHP内核探索之变量(3)- hash table),我们已经知道,数组在PHP的底层实际上是HashTable(链接法解决冲突),本文将对最常用的函数系列-数组操作的相关函数做进一步的跟踪. ...
- PHP内核探索之变量(1)Zval
作为数据的容器,我们常常需要跟变量打交道,不管这个变量是数字.数组.字符串.对象还是其他,因而可以说变量是构成语言的不可或缺的基础.本文是PHP内核探索之变量的第一篇,主要介绍zval的基本知识,包括 ...
- Android进程管理及静态变量垃圾回收
1.Android静态变量的生命周期 静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的时候分配内存的,并且存在于方法 区.当类被卸载的时候,静态变量被销毁. 在PC机的客户端程 ...
- Android静态变量使用陷阱
静态变量大家再熟悉不过了,本来没什么好重复的.事情起因是这样的,最近测试那边反应正在做的一个产品总是莫名其妙的显示不出某些数据,甚至闪退崩溃,仔细查了几遍发现没什么问题,最后百般周折发现在那部测试机上 ...
- 常量和静态变量会先载入内存后在进行执行php代码
static $test=1;//在php执行前就已经写入内存$test++;var_dump($test);static $test=10;//在php执行前就已经写入内存var_dump($tes ...
随机推荐
- SQL select 执行顺序
一.sql语句的执行步骤:1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义.2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限.3)视图转换,将涉及视图的查询语 ...
- 利用fetch进行POST传参
fetch(config.host+"url",{ method:"POST", mode: 'cors',跨域请求 headers: { ...
- 【POJ1811】Prime Test
[题目大意] 若n是素数,输出“Prime”,否则输出n的最小素因子,(n<=2^54) [题解] 和bzoj3667差不多,知识这道题没那么坑. 直接上Pollord_Rho和Rabin_Mi ...
- Python下Pip的安装【get-pip】
1.下载 下载https://bootstrap.pypa.io/get-pip.py 如果不能下载,可下载:http://files.cnblogs.com/files/zhangzhiming/g ...
- eclipse添加web项目报错“Target runtime Apache Tomcat v7.0 is not defined.”
项目检出后,发现是Tomcat7 发布的,修改文件: 工作空间--->项目名称--->.settings--->org.eclipse.wst.common.project.face ...
- [C++] any number to binary (Bit manipulation)
any number to binary (Bit manipulation)
- Ext.data.association.hasMany一对多模型使用示例
来自<sencha touch权威指南>第11章,323页开始 --------------------------------------------------- index.html ...
- [OS] 如何在远程机器上用ctrl+alt+del键修改登录用户的密码
远程登录某台机器,想修改当前登录用户的密码,系统提示按Ctrl+Alt+Del,在出现的界面里修改密码 但我一按这三个键,是在我本地客户机生效,而不是在远程服务器. 答案 : 向远程桌面发送Ctrl+ ...
- DESC和 ACS
用 DESC 表示按倒序排序(即:从大到小排序)用 ACS 表示按正序排序(即:从小到大排序)
- iframe是怎么跳转的
在main.jsp中 <iframe frameborder="0" marginheight="0" marginwidth="0" ...