Bug #53863 [Com]: scalar reference of array element has unintended side effects
| From: | sohagan at gmail dot com | Date: | Wed, 19 Nov 2014 15:32:39 +0000 |
| Subject: | Bug #53863 [Com]: scalar reference of array element has unintended side effects | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-188683@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=53863&edit=1
ID: 53863
Comment by: sohagan at gmail dot com
Reported by: elrah at polyptych dot com
Summary: scalar reference of array element has unintended
side effects
Status: Not a bug
Type: Bug
Package: Variables related
Operating System: CentOS 5.5
PHP Version: 5.3.5
Block user comment: N
Private report: N
New Comment:
Here's the relevant documention showing that this is expected behaviour:
http://php.net/manual/en/language.references.whatdo.php
(search for "Assignment of array variables")
Previous Comments:
------------------------------------------------------------------------
[2014-11-18 21:15:48] rasmus@php.net
There isn't actually a bug here. This is how references work and there is no change of
behaviour from one version to the next. All versions of PHP give the same result here.
------------------------------------------------------------------------
[2014-11-18 20:07:33] sohagan at gmail dot com
In PHP 5.3.3 (on Linux 2.6.32-431.23.3.el6.x86_64), there is a related(identical?) bug which causes
the last element of an array to be passed/assigned by reference if its parent array is used as a
reference.
For example, foreach ($my_array as &$array_val) {...} will cause the last element of $my_array
to be assigned by reference:
$my_new_array = $my_array;
$my_new_array[4] = null; // if $my_array's last index is 4, this will nullify that value
too
and passed by reference:
function dont_touch($param) { // modify $param here }
dont_touch($my_array[4]); // $my_array[4] will be modified
This can be fixed by unsetting the reference to the array value after the foreach loop.
unset($array_val); // after the foreach loop
Try running this code and comment/uncomment the line containing "unset".
<?php
$thingies = array(array(1,2,3,4),array(1,2,3,4));
var_dump($thingies);
foreach ($thingies as &$things) {
foreach ($things as $thing) {
$thing += 1;
}
}
unset($things);
$copythings = $thingies;
$copythings[1][0] += 1;
$copythings[1][1] += 1;
$copythings[1][2] += 1;
$copythings[1][3] += 1;
var_dump($thingies);
?>
------------------------------------------------------------------------
[2011-01-28 07:45:28] elrah at polyptych dot com
Description:
------------
Adding a scalar reference to an array element changes array assignment behavior.
In a regular array assignment, elements are all copied by value. But if a scalar
reference has been made to an array element, that element is copied by reference
in a subsequent array assignment. The code looks exactly the same, so the
behavior shouldn't change just because there's a reference floating out there
somewhere.
Test script:
---------------
<?php
$arr1 = array(1);
echo "\nbefore:\n";
echo "\$arr1[0] == {$arr1[0]}\n";
$arr2 = $arr1;
$arr2[0]++;
echo "\nafter:\n";
echo "\$arr1[0] == {$arr1[0]}\n";
echo "\$arr2[0] == {$arr2[0]}\n";
$arr3 = array(1);
$a =& $arr3[0];
echo "\nbefore:\n";
echo "\$a == $a\n";
echo "\$arr3[0] == {$arr3[0]}\n";
$arr4 = $arr3;
$arr4[0]++;
echo "\nafter:\n";
echo "\$a == $a\n";
echo "\$arr3[0] == {$arr3[0]}\n";
echo "\$arr4[0] == {$arr4[0]}\n";
Expected result:
----------------
before:
$arr1[0] == 1
after:
$arr1[0] == 1
$arr2[0] == 2
before:
$a == 1
$arr3[0] == 1
after:
$a == 1
$arr3[0] == 1
$arr4[0] == 2
Actual result:
--------------
before:
$arr1[0] == 1
after:
$arr1[0] == 1
$arr2[0] == 2
before:
$a == 1
$arr3[0] == 1
after:
$a == 2
$arr3[0] == 2
$arr4[0] == 2
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=53863&edit=1