PHP错误抑制符(@)导致引用传参失败Bug的分析
看下面的例子: 这个问题,我之前没有遇到过,所以首先去找找相关资料,看看有没有现成的答案,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网友提供的这个有趣的问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |