Doc #80541 [Opn->Ver]: foreach by-val vs. by-ref traversal unclear

From: Date: Tue, 20 Jul 2021 09:48:12 +0000
Subject: Doc #80541 [Opn->Ver]: foreach by-val vs. by-ref traversal unclear
References: 1  Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-18974@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=80541&edit=1

 ID:                 80541
 Updated by:         cmb@php.net
 Reported by:        andre at webkr dot de
-Summary:            Using a reference as iterator variable turns the
                     whole array into a reference
+Summary:            foreach by-val vs. by-ref traversal unclear
-Status:             Open
+Status:             Verified
 Type:               Documentation Problem
 Package:            Arrays related
 PHP Version:        8.0.0
 Block user comment: N
 Private report:     N

 New Comment:

This not related to the fact that $arr is turned into a
reference[1], but rather that foreach by-val traversal actually
happens on a (separated) copy of the original array[2], while
by-ref traversal happens on the original array.

This is by design, so, yes, documentation issue.

[1] <https://3v4l.org/DuEcf>
[2] <https://3v4l.org/8LL0C>


Previous Comments:
------------------------------------------------------------------------
[2021-05-24 00:20:53] a3ron223 at gmail dot com

The foreach function will continue to run until it has reached the end of the array.
If the foreach function adds another key to the array every time it runs, then it will not stop
running (until it exhausts the script's memory).

I'm a little surprised that it isn't documented.

------------------------------------------------------------------------
[2020-12-22 09:54:52] andre at webkr dot de

Description:
------------
I'm not sure whether this is a bug or a documentation bug. I'd consider it a bug but given
the promise of backwards compatibility it's unlikely to be fixed.

If the iterator variable in a foreach is a reference, then the whole array becomes a reference and
it is no longer safe to append to the array. This is true even when the iterator variable is not
actually used anywhere.

At least this behavior should be documented. The documentation currently says:

> In order to be able to directly modify array elements within the loop precede $value with
> &. In that case the value will be assigned by reference.

It says nothing about the array itself, only about the array values, reenforcing the wrong
impression that it is still safe to add or remove array elements.

Test script:
---------------
$arr = ['a','b','c'];

foreach ($arr as &$dummy)
{
    $arr []= 'foo';
}

var_dump($arr);

Expected result:
----------------
array(6) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "c"
  [3]=>
  string(3) "foo"
  [4]=>
  string(3) "foo"
  [5]=>
  string(3) "foo"
}

Actual result:
--------------
Fatal error: Allowed memory size of [...] bytes exhausted


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=80541&edit=1


Thread (6 messages)

« previous php.doc.bugs (#18974) next »