Analysis of the Bug of reference passing failure caused by the PHP error blocker. Let's take a look at the following example :? Php $ arrayarray (, 3); functionadd (} add (@ $ array); print_r ($ array); ** at this time, $ array is not changed, and the output is: array ([0] 1 [1 see the following example:
The code is as follows:
$ Array = array (1, 2, 3 );
Function add (& $ arr ){
$ Arr [] = 4;
}
Add (@ $ array );
Print_r ($ array );
/**
At this time, $ array does not change and the output is:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
*/
Add ($ array );
Print_r ($ array );
/**
If error suppression is not used, the output is normal:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
*/
?>
This problem, I have not met before, so first go to the relevant information to see if there is a ready-made answer, Goolge a bit, found that although someone has reported a similar Bug to PHP: http://bugs.php.net/bug.php? Id = 47623, but PHP has not been resolved yet and no response is provided.
No way, I can only analyze it by myself. I have previously introduced the principle of the error blocker in my article (a deep understanding of PHP principles, error blocker and embedded HTML). in principle, error suppression only modifies the level of error_reporting, which does not affect the function calling mechanism between contexts. it can only be tested in the field.
After gdb tracking, it is found that the parameter passing opcode before the function call is different after the error port is used:
The code is as follows:
// When the error blocker is not used
OPCODE = SEND_REF
// After the error suppression symbol is used
OPCODE = SEND_VAR_NO_RE
The problem was initially located, but why is the difference?
Since OPCODE is different, it must have taken different branches in the syntax analysis phase. when we think of this layer, the problem will be well located,
Originally, in the PHP syntax analysis phase, the entry in the form of "@" + expr is reduced to expr_without_variable, and the meaning of this node is that there is no variable value, that is, the literal value, we all know that the literal value cannot be referenced (because it is not a variable), so this difference will occur.
The specific process is as follows:
1. syntax analysis stage:
The code is as follows:
Expr_without_variable:
//... Omitted
| '@' {Zend_do_begin_silence (& $1 TSRMLS_CC );}
Expr {zend_do_end_silence (& $1 TSRMLS_CC); $ = $3 ;}
// The ZEND_SEND_VAL branch is used here.
Non_empty_function_call_parameter_list:
Expr_without_variable {...} // The branch is incorrect.
| Variable {...} // normal situation
Therefore, different opcodes are generated during compilation, which also leads to the appearance of problems.
Finally, I have explained the cause on the PHP bug page. if you are interested, you can check out my poor English skills. finally, thank you for providing this interesting question.
The pipeline code is as follows :? Php $ array = array (, 3); function add (} add (@ $ array); print_r ($ array);/** at this time, $ array is not changed and the output is: array ([0] = 1 [1...