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 ...
随机推荐
- CSS选择器的匹配规则
css选择器是从右向左匹配的, 比如:.list a {color:blue;} 先解析到 a 标签,并将页面上所有 a 标签的字体颜色都按照 color:blue 进行渲染(蓝色),再解析到 .li ...
- 3D Math Keynote
[3DMathKeynote] 1.常用公式. 1)(A*B)^T = B^T*A^T. 2)(A*B)^-1 = B^-1*A^-1. 3)|A*B| = |A|*|B|. 4)|M^T|=|M ...
- Spark会产生shuffle的算子
去重 def distinct() def distinct(numPartitions: Int) 聚合 def reduceByKey(func: (V, V) => V, numParti ...
- rocketmq--消息的产生(普通消息)
与消息发送紧密相关的几行代码: 1. DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName") ...
- java反射对实体类取值和赋值,可以写成通过实体类获取其他元素的数据,很方便哦~~~
项目中需要过滤前面表单页面中传过来的实体类的中的String类型变量的前后空格过滤,由于前几天看过一个其他技术博客的的java反射讲解,非常受益.于是,哈哈哈 public static <T& ...
- CentOS 6.4一键自动化安装ISO镜像光盘
下载CentOS-6.4-x86_64-minimal.iso 1 http://mirrors.163.com/centos/6.4/isos/x86_64/CentOS-6.4-x86_64-mi ...
- DPDK收发包全景分析
前言:DPDK收发包是基础核心模块,从网卡收到包到驱动把包拷贝到系统内存中,再到系统对这块数据包的内存管理,由于在处理过程中实现了零拷贝,数据包从接收到发送始终只有一份,对这个报文的管理在前面的mem ...
- Java泛型中的通配符
Java泛型中的通配符可以直接定义泛型类型的参数.而不用把该函数定义成泛型函数. public class GenericsTest { public static void main(String[ ...
- Python 简单模块学习
1. openpyxl / xlrd / xlwt => 操作Excel 文件(xlsx格式) => xlrd + xlwt : 只能操作xls文件,分别负责读写, 暂时不讨论 => ...
- idea 启动报错问题
Artifact SpiderServer:war exploded: Error during artifact deployment. See server log for details. 1. ...