<?php
$a="abc";
$b="def";
unset($a,$b);
echo $a."\n";
echo $b."\n";

1)词法分析

<ST_IN_SCRIPTING>"unset" {
return T_UNSET;
}

2)语法分析

unticked_statement:

|    T_UNSET '(' unset_variables ')' ';'          //unset($a,$b) 还能这么用呢,第一次知道

unset_variables:
        unset_variable

|    unset_variables ',' unset_variable

;

unset_variable:

        variable    { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }

;

3)生成opcode

void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
{
zend_op *last_op; zend_check_writable_variable(variable); if (variable->op_type == IS_CV) {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_UNSET_VAR;
SET_NODE(opline->op1, variable);
SET_UNUSED(opline->op2);
SET_UNUSED(opline->result);
opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
} else {
//不是IS_CV类型的处理
}
}

4)执行opcode

static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval tmp, *varname;
HashTable *target_symbol_table; SAVE_OPLINE();
if (IS_CV == IS_CV &&
IS_UNUSED == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
if (EG(active_symbol_table)) {
zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.var); zend_delete_variable(EX(prev_execute_data), EG(active_symbol_table), cv->name, cv->name_len+, cv->hash_value TSRMLS_CC); //从active_symbol_table中清除cv->name以及相应值,再从CV数组中清除此值
EX_CV(opline->op1.var) = NULL;
} else if (EX_CV(opline->op1.var)) {
zval_ptr_dtor(EX_CV(opline->op1.var));
EX_CV(opline->op1.var) = NULL;
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
//不会被执行了
}
 
#define CV_DEF_OF(i) (EG(active_op_array)->vars[i])

#undef EX_CV
#define EX_CV(var) EX(CVs)[var]

#undef EX_CVs

#define EX_CVs() EX(CVs)

#undef EX_T

#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))

#undef EX_Ts

#define EX_Ts() EX(Ts)

 

ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const char *name, int name_len, ulong hash_value TSRMLS_DC) /* {{{ */
{

if (zend_hash_quick_del(ht, name, name_len, hash_value) == SUCCESS) {

name_len--;

while (ex && ex->symbol_table == ht) {

int i;

if (ex->op_array) {

                for (i = 0; i < ex->op_array->last_var; i++) {

if (ex->op_array->vars[i].hash_value == hash_value &&

ex->op_array->vars[i].name_len == name_len &&

!memcmp(ex->op_array->vars[i].name, name, name_len)) {

ex->CVs[i] = NULL;

break;

}

}

}

ex = ex->prev_execute_data;

}

}

}

ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag)

{

uint nIndex;

Bucket *p;

#ifdef ZEND_SIGNALS

TSRMLS_FETCH();

#endif

IS_CONSISTENT(ht);

if (flag == HASH_DEL_KEY) {

        h = zend_inline_hash_func(arKey, nKeyLength);

}

nIndex = h & ht->nTableMask;

p = ht->arBuckets[nIndex];

    while (p != NULL) {

if ((p->h == h)

&& (p->nKeyLength == nKeyLength)

&& ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp() check) */

|| !memcmp(p->arKey, arKey, nKeyLength))) { /* String index */

HANDLE_BLOCK_INTERRUPTIONS();

if (p == ht->arBuckets[nIndex]) {

ht->arBuckets[nIndex] = p->pNext;

} else {

p->pLast->pNext = p->pNext;

}

if (p->pNext) k{

p->pNext->pLast = p->pLast;

}

if (p->pListLast != NULL) {

p->pListLast->pListNext = p->pListNext;

} else {

/* Deleting the head of the list */

ht->pListHead = p->pListNext;

}

if (p->pListNext != NULL) {

p->pListNext->pListLast = p->pListLast;

} else {

ht->pListTail = p->pListLast;

}

if (ht->pInternalPointer == p) {

ht->pInternalPointer = p->pListNext;

}

if (ht->pDestructor) {

ht->pDestructor(p->pData);

}

if (p->pData != &p->pDataPtr) {

pefree(p->pData, ht->persistent);

}

pefree(p, ht->persistent);

HANDLE_UNBLOCK_INTERRUPTIONS();

ht->nNumOfElements--;

return SUCCESS;

}

p = p->pNext;

}

return FAILURE;

}

php unset变量的更多相关文章

  1. php面试题7(1、unset变量是删除栈变量,并不删除堆变量)(2、php爬虫特别简单: 可以file_get_contents和直接fopen)

    php面试题7(1.unset变量是删除栈变量,并不删除堆变量)(2.php爬虫特别简单: 可以file_get_contents和直接fopen) 一.总结 1.unset变量是删除栈变量,并不删除 ...

  2. unset变量释放内存不起作用

    unset()函数只能在变量值占用内存空间超过256字节时才会释放内存空间. 只有当指向该变量的所有变量(如引用变量)都被销毁后,才会释放内存.

  3. linux学习之十、变量的取用与配置:echo, 变量配置守则, unset

    vim vim 的环境设定参数 :set nu :set nonu 就是设定与取消行号啊! :set hlsearch :set nohlsearch hlsearch 就是 high light s ...

  4. thinkphp 控制器unset删除对象变量失败。。

    今儿开发过程中发现 tp是unset 变量失败..具体代码 foreach( $this->menu as $k => $v){ if(0 == $v['flag']) unset($th ...

  5. 第9章 Shell基础(3)_Bash的变量

    4. Bash的变量 4.1 用户自定义变量 4.1.1 什么是变量 变量是计算机的内存单元,其中存放的值可以改变.当Shell脚本需要保存一些信息时,如一个文件名或是一个数字,就把它存放在一个变量中 ...

  6. 三、Shell变量类型和运算符

    一.Shell变量的应用 1.Shell变量的种类     ·用户自定义变量:由用户自己定义.修改和使用     ·预定义变量:Bash预定义的特殊变量,不能直接修改     ·位置变量:通过命令行给 ...

  7. shell编程之变量

    变量: 变量由字母.数字._ 组成,不能以数字开头 长度不能超过255个字符 在bash中,变量的默认类型是字符串类型 变量分类: 1.用户自定义变量:只在当前shell生效,是局部变量 定义方法: ...

  8. Shell 的变量功能

    搜寻路径PATH(系统预设变量) 执行命令时,系统透过PATH得路径顺序搜寻指令,如果再搜寻完后还找不到该指令,就会打印错误讯息[command not fount].   环境变量 进入shell之 ...

  9. Linux中的输入重定向,变量

    1 :分号 格式:命令1:命令2;命令3 说明:命令之间用分号隔开是顺序执行,命令之间没有任何逻辑关系 2  &&  逻辑与 格式:命令1 && 命令2 说明:命令1正 ...

随机推荐

  1. 学习bn算法

    好处: 1.归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低: 2.另外一方面,一旦每批训练数据的分布各不相同(b ...

  2. client.HConnectionManager$HConnectionImplementation: Can't get connection to ZooKeeper: KeeperErrorCode = ConnectionLoss for /hbase

    解决方法:hbase 未成功启动 1.关闭防火墙:service iptables stop 2.start-hbase.sh

  3. Python特殊方法

    # __slots__如果要限制添加的属性,例如,Student类只允许添加 name.gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现. # __sl ...

  4. Django入门与实践-第13章:表单处理(完结)

    http://127.0.0.1:8000/boards/1/ http://127.0.0.1:8000/boards/2/ http://127.0.0.1:8000/boards/3/ http ...

  5. 静态代码块和this

    /* 静态代码块.随着类的加载而执行.而且只执行一次. 作用: 用于给类进行初始化. */class StaticCode{ static int num ; static { num = 10;// ...

  6. 常用的SLAM解决方案

    ORB SLAM 可以去Github上自己搜索现成的SLAM程序包 在此基础上做优化 视觉SLAM的分类方法:按摄像头的多少分为单目和双目,按是否使用概率方法分为概率法和图法 链接 学习SLAM重要的 ...

  7. B-tree B+tree适合文件系统索引和MySQL索引

    B-树 B-树,这里的 B 表示 balance( 平衡的意思),B-树是一种多路自平衡的搜索树 它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点.下图是 B-树的简化图. B-树 ...

  8. java.util.Date与java.sql.Date的关系和转换方法(转)

    在ResultSet中我们经常使用的setDate或getDate的数据类型是java.sql.Date,而在平时java程序中我们一般习惯使用 java.util.Date. 因此在DAO层我们经常 ...

  9. java web开发过程中的“\”指的是什么,如何区分

  10. Android-fragment-ListView展示-v4支持包

    昨天写的这几篇博客,Android-fragment简介-fragment的简单使用,Activity-fragment-ListView展示,Android-fragment生命周期,Android ...