PHP錯(cuò)誤抑制符(@)導(dǎo)致引用傳參失敗Bug的分析
<?php
$array = array(1,2,3);
function add (&$arr) {
$arr[] = 4;
}
add(@$array);
print_r($array);
/**
此時(shí), $array沒有改變, 輸出:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
*/
add($array);
print_r($array);
/**
不使用錯(cuò)誤抑制的情況下, 輸出正常:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
*/
?>
這個(gè)問題, 我之前沒有遇到過, 所以首先去找找相關(guān)資料, 看看有沒有現(xiàn)成的答案, Goolge了一番, 發(fā)現(xiàn)雖然有人已經(jīng)向PHP報(bào)了類似的Bug:http://bugs.php.net/bug.php?id=47623, 但PHP官方還沒有解決, 也沒有給出答復(fù).
沒辦法, 只能自己分析了, 之前我曾經(jīng)在文章中介紹過錯(cuò)誤抑制符的原理( 深入理解PHP原理之錯(cuò)誤抑制與內(nèi)嵌HTML), 從原理上來說, 錯(cuò)誤抑制只是修改了error_reporting的level, 按理來說不會影響到上下文之間的函數(shù)調(diào)用的機(jī)制. 只能通過實(shí)地試驗(yàn)了.
經(jīng)過gdb跟蹤, 發(fā)現(xiàn)在使用了錯(cuò)誤移植符以后, 函數(shù)調(diào)用前的傳參opcode不同:
//沒有使用錯(cuò)誤抑制符的時(shí)候
OPCODE = SEND_REF
//使用了錯(cuò)誤抑制符號以后
OPCODE = SEND_VAR_NO_RE
問題初步定位了, 但是造成這種差異的原因又是什么呢?
既然OPCODE不同, 那么肯定是在語法分析的階段, 走了不同的分支了, 想到這一層, 問題也就好定位了,
原來, PHP語法分析階段, 把形如 “@”+expr的條目, 規(guī)約成了expr_without_variable, 而這種節(jié)點(diǎn)的意義就是沒有變量的值, 也就是字面值, 我們都知道字面值是不能傳遞引用的(因?yàn)樗皇亲兞?, 所以, 就會導(dǎo)致這種差異.
具體過程如下:
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 { ....} //錯(cuò)誤的走了這個(gè)分支
| variable {..... } //正常情況
所以導(dǎo)致在編譯期間, 生成了不同的OPCODE, 也導(dǎo)致了問題的表象.
最后, 我已經(jīng)把原因在PHP的這個(gè)bug頁做了說明, 有興趣的可以去看看我的爛英語水平. 最后謝謝cici網(wǎng)友提供的這個(gè)有趣的問題.
- php函數(shù)間的參數(shù)傳遞(值傳遞/引用傳遞)
- PHP通過引用傳遞參數(shù)用法分析
- php 獲取可變函數(shù)參數(shù)的函數(shù)
- PHP入門教程之自定義函數(shù)用法詳解(創(chuàng)建,調(diào)用,變量,參數(shù),返回值等)
- php指定函數(shù)參數(shù)默認(rèn)值示例代碼
- php定義參數(shù)數(shù)量可變的函數(shù)用法實(shí)例
- php 函數(shù)使用可變數(shù)量的參數(shù)方法
- php可變長參數(shù)處理函數(shù)詳解
- php函數(shù)與傳遞參數(shù)實(shí)例分析
- PHP函數(shù)按引用傳遞參數(shù)及函數(shù)可選參數(shù)用法示例
相關(guān)文章
php給一組指定關(guān)鍵詞添加span標(biāo)簽的方法
這篇文章主要介紹了php給一組指定關(guān)鍵詞添加span標(biāo)簽的方法,涉及php正則替換的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03
比較discuz和ecshop的截取字符串函數(shù)php版
網(wǎng)上看到一篇文章 discuz和ecshop截取字符串的兩個(gè)函數(shù),比較了一下兩個(gè)版本的函數(shù),都各有局限,只能在特定的前提下使用,但是學(xué)習(xí)一下有利于拓寬思路,了解PHP的擴(kuò)展功能2012-09-09
php+mysql+jquery實(shí)現(xiàn)簡易的檢索自動(dòng)補(bǔ)全提示功能
這篇文章主要介紹了php+mysql+jquery實(shí)現(xiàn)簡易的檢索自動(dòng)補(bǔ)全提示功能,涉及基于jQuery的ajax數(shù)據(jù)庫查詢與事件動(dòng)態(tài)響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下2017-04-04
編寫php應(yīng)用程序?qū)崿F(xiàn)摘要式身份驗(yàn)證的方法詳解
本篇文章是對編寫php應(yīng)用程序?qū)崿F(xiàn)摘要式身份驗(yàn)證的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
php實(shí)現(xiàn)xml轉(zhuǎn)換數(shù)組的方法示例
這篇文章主要介紹了php實(shí)現(xiàn)xml轉(zhuǎn)換數(shù)組的方法,結(jié)合具體實(shí)例形式分析了php操作xml格式文件實(shí)現(xiàn)轉(zhuǎn)換數(shù)組的相關(guān)操作技巧,涉及xml格式數(shù)據(jù)的載入、遍歷、轉(zhuǎn)換等方法,需要的朋友可以參考下2017-02-02

