PHP错误抑制符(@)导致引用传参失败Bug的分析


Posted in PHP onMay 02, 2011

看下面的例子:

<?php 
$array = array(1,2,3); 
function add (&$arr) { 
$arr[] = 4; 
} 
add(@$array); 
print_r($array); 
/** 
此时, $array没有改变, 输出: 
Array 
( 
[0] => 1 
[1] => 2 
[2] => 3 
) 
*/ 
add($array); 
print_r($array); 
/** 
不使用错误抑制的情况下, 输出正常: 
Array 
( 
[0] => 1 
[1] => 2 
[2] => 3 
[3] => 4 
) 
*/ 
?>

这个问题, 我之前没有遇到过, 所以首先去找找相关资料, 看看有没有现成的答案, Goolge了一番, 发现虽然有人已经向PHP报了类似的Bug:http://bugs.php.net/bug.php?id=47623, 但PHP官方还没有解决, 也没有给出答复.

没办法, 只能自己分析了, 之前我曾经在文章中介绍过错误抑制符的原理( 深入理解PHP原理之错误抑制与内嵌HTML), 从原理上来说, 错误抑制只是修改了error_reporting的level, 按理来说不会影响到上下文之间的函数调用的机制. 只能通过实地试验了.

经过gdb跟踪, 发现在使用了错误移植符以后, 函数调用前的传参opcode不同:

//没有使用错误抑制符的时候 
OPCODE = SEND_REF 
//使用了错误抑制符号以后 
OPCODE = SEND_VAR_NO_RE

问题初步定位了, 但是造成这种差异的原因又是什么呢?

既然OPCODE不同, 那么肯定是在语法分析的阶段, 走了不同的分支了, 想到这一层, 问题也就好定位了,

原来, PHP语法分析阶段, 把形如 “@”+expr的条目, 规约成了expr_without_variable, 而这种节点的意义就是没有变量的值, 也就是字面值, 我们都知道字面值是不能传递引用的(因为它不是变量), 所以, 就会导致这种差异.

具体过程如下:
1. 语法分析阶段:

expr_without_variable: 
//...有省略 
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } 
expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; } 
//此处走了ZEND_SEND_VAL分支 
non_empty_function_call_parameter_list: 
expr_without_variable { ....} //错误的走了这个分支 
| variable {..... } //正常情况

所以导致在编译期间, 生成了不同的OPCODE, 也导致了问题的表象.
最后, 我已经把原因在PHP的这个bug页做了说明, 有兴趣的可以去看看我的烂英语水平. 最后谢谢cici网友提供的这个有趣的问题.
PHP 相关文章推荐
PHP中使用crypt()实现用户身份验证的代码
Sep 05 PHP
PHP 正则表达式之正则处理函数小结(preg_match,preg_match_all,preg_replace,preg_split)
Oct 05 PHP
php更新mysql后获取影响的行数发生异常解决方法
Mar 28 PHP
ueditor 1.2.6 使用方法说明
Jul 24 PHP
phpphp图片采集后按原路径保存图片示例
Feb 18 PHP
PHP文件上传判断file是否己选择上传文件的方法
Nov 10 PHP
smarty内部日期函数html_select_date()用法实例分析
Jul 08 PHP
PHP结合jQuery插件ajaxFileUpload实现异步上传文件实例
Aug 17 PHP
PHP将数据导出Excel表中的实例(投机型)
Jul 31 PHP
laravel高级的Join语法详解以及使用Join多个条件
Oct 16 PHP
php中try catch捕获异常实例详解
Aug 06 PHP
搭建PhpStorm+PhpStudy开发环境的超详细教程
Sep 17 PHP
一些PHP Coding Tips(php小技巧)[2011/04/02最后更新]
May 02 #PHP
PHP中使用gettext来支持多语言的方法
May 02 #PHP
php中神奇的fastcgi_finish_request
May 02 #PHP
PHP开发不能违背的安全规则 过滤用户输入
May 01 #PHP
PHP 调试工具Debug Tools
Apr 30 #PHP
php debug 安装技巧
Apr 30 #PHP
vs中通过剪切板循环来循环粘贴不同内容
Apr 30 #PHP
You might like
php处理json格式数据经典案例总结
2016/05/19 PHP
php解析mht文件转换成html的实例
2017/03/13 PHP
php静态成员方法和静态的成员属性的使用方法
2017/10/26 PHP
实例讲解php将字符串输出到HTML
2019/01/27 PHP
php菜单/评论数据递归分级算法的实现方法
2019/08/01 PHP
从新浪弄下来的全屏广告代码 与使用说明
2007/03/15 Javascript
Input 特殊事件onpopertychange和oninput
2009/06/17 Javascript
jQuery的强大选择器小结
2009/12/27 Javascript
js iframe跨域访问(同主域/非同主域)分别深入介绍
2013/01/24 Javascript
javaScript实现浮点数转十六进制字符
2013/10/29 Javascript
用js代码改变单选框选中状态的简单实例
2013/12/18 Javascript
详解javascript数组去重问题
2015/11/06 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
2016/05/31 Javascript
JS如何设置元素样式的方法示例
2017/08/28 Javascript
使用Vuex解决Vue中的身份验证问题
2018/09/28 Javascript
解决vue中使用proxy配置不同端口和ip接口问题
2019/08/14 Javascript
vue-cli设置publicPath小记
2020/04/14 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
python 中的列表解析和生成表达式
2011/03/10 Python
利用Python命令行传递实例化对象的方法
2016/11/02 Python
基于Python3 逗号代码 和 字符图网格(详谈)
2017/06/22 Python
python中使用%与.format格式化文本方法解析
2017/12/27 Python
Linux下安装python3.6和第三方库的教程详解
2018/11/09 Python
Python实现对字典分别按键(key)和值(value)进行排序的方法分析
2018/12/19 Python
python实现图像全景拼接
2020/03/27 Python
什么是python类属性
2020/06/10 Python
Opencv+Python识别PCB板图片的步骤
2021/01/07 Python
基于第一个PhoneGap(cordova)的应用详解
2013/05/03 HTML / CSS
Stefania Mode英国:奢华设计师和时尚服装
2017/10/23 全球购物
W Hamond官网:始于1979年的钻石专家
2020/07/20 全球购物
电子专业推荐信范文
2013/11/18 职场文书
家教广告词
2014/03/19 职场文书
高中生操行评语
2014/04/25 职场文书
旅游专业毕业生自荐书
2014/06/30 职场文书
Python连续赋值需要注意的一些问题
2021/06/03 Python
利用uni-app生成微信小程序的踩坑记录
2022/04/05 Javascript