Bug #74020 [Ver->Csd]: Foreach-by-reference + assignment may recreate unexpected key references
| From: | requinix@php.net | Date: | Sun, 17 Feb 2019 12:37:23 +0000 |
| Subject: | Bug #74020 [Ver->Csd]: Foreach-by-reference + assignment may recreate unexpected key references | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-219614@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=74020&edit=1
ID: 74020
Updated by: requinix@php.net
Reported by: icarpenter at leadid dot com
Summary: Foreach-by-reference + assignment may recreate
unexpected key references
-Status: Verified
+Status: Closed
Type: Bug
Package: Scripting Engine problem
PHP Version: 7.0.15
-Assigned To:
+Assigned To: requinix
Block user comment: N
Private report: N
New Comment:
They're both references to the same thing, because
> I'd expect $item to be a reference to the last array item after the first loop
that's not what is actually happening. A reference is not technically to another variable but
to a shared value in memory. $item does not "point" to the last item in the array, rather
it and the array item both use the same shared value. Thus why they are both references. unset()ing
$item destroys one of the two references, and since there's only one left it does not need to
be a reference anymore.
Closing because as far as I know the originally-reported bug only affects PHP 7.0 and that is no
longer supported.
Previous Comments:
------------------------------------------------------------------------
[2019-02-17 12:29:06] glueball at gmail dot com
I've found another instance of this same issue (I think it's the same):
https://3v4l.org/oe98G
While it's true that it gets fixed easily by unsetting the variable after the loop, this
behavior is very unexpected, and does not seem right. I'd expect $item to be a reference to the
last array item after the first loop, but apparently the last item in the array is also a reference
to "something" (as can be seen by the "&" sign in the intermediate var_dump)
------------------------------------------------------------------------
[2018-10-23 22:59:41] fra dot martin at free dot fr
Previous comment was supposed to end at «...Sorry for my previous useless comment.»
------------------------------------------------------------------------
[2018-10-23 22:54:05] fra dot martin at free dot fr
I know what a reference is...
But you are right, my expectation is false. Indeed I did not take time to understand step by step
what happened here:
- the first foreach leaves $item referencing the last array's element
- the second foreach loop assigns successively $item with the 1st value (which also modifies the
last element since $item is a pointer on it, its value is now 1), then the 2nd one (which re-assigns
$item and the last element, its value becomes 2), then the 3rd one, which re-assings $item and
itself with its current value '2'.
Sorry for my previous useless comment.
In my previous example, the first foreach loop creates a reference variable and makes it reference
successively the 1st, 2nd and 3rd element in the array. After the first foreach loop, I understand
that $item still references the last array's element (int(3)), that's what would give a
'var_dump($item);'
The second foreach loop uses the same variable (still a reference since created as such in the first
foreach loop) and iterates over each element, assigning
------------------------------------------------------------------------
[2018-10-23 21:30:34] spam2 at rhsoft dot net
your expectation is imply wrong
foreach($items as &$item);
unset($item);
foreach($items as $item);
you miss the unset!
either understand what references are or don't use them
------------------------------------------------------------------------
[2018-10-23 20:25:16] fra dot martin at free dot fr
This is probably the same issue, much more direct and very disturbing for me. These two simple
foreach loops do nothing, they just use the same variable name, once by reference, once by value:
the last array element always becomes a copy of the penultimate element!
$items = [1,2,3];
foreach($items as &$item);
foreach($items as $item);
echo array_pop($items);
Expected result: 3
Actual result: 2
Expected result:
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=74020
--
Edit this bug report at https://bugs.php.net/bug.php?id=74020&edit=1