php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #29950 Nondeterministic behavior of array inner pointer
Submitted: 2004-09-02 14:22 UTC Modified: 2004-09-26 20:38 UTC
From: tomas_matousek at hotmail dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 5.0.1 OS: all
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: tomas_matousek at hotmail dot com
New email:
PHP Version: OS:

 

 [2004-09-02 14:22 UTC] tomas_matousek at hotmail dot com
Description:
------------
In the manual page describing each() function is the following caution:
"Because assigning an array to another variable resets the original arrays pointer, ..."

I think that this is a bug, although it is documented and treated as feature.
I realized that the pointer is reset when a copy of an  array is made. However, PHP makes some optimizations which prevents unnecessary array copying (which is good feature).
Since these optimizations are not known for users (and shouldn't be) the behavior of inner pointer is thus non-deterministic from user's point of view.

See the follwoing code. 
Its output depends on whether the statement $b[] = 1; is commented or not.


Reproduce code:
---------------
function f($a) { $b = $a; /*$b[] = 1;*/ return $b; }

$arrayOuter = array("key1","key2");
$arrayInner = array("0","1");

while(list(,$o) = each($arrayOuter))
{
        $q = f($arrayInner);
	while(list(,$i) = each($arrayInner)) 
        {
		print "inloop $i for $o\n";
	}
}



Expected result:
----------------
inloop 0 for key1
inloop 1 for key1

Actual result:
--------------
inloop 0 for key1
inloop 1 for key1
inloop 0 for key2
inloop 1 for key2



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-09-03 10:53 UTC] andrey@php.net
 I think it is mentioned in the manual that PHP uses copy-on-write technique. This means that  if
$a = array(1,2,3);
and 
$b = $a;
there is _only_ 1 array and $b reference this array. When change has been made the copy-on-write starts to work. AFAIK it is not only for arrays...
Simple example :
php -r '$a=str_repeat("a", 10000000);while ($i++<2000) ${"a".$i} = $a;

This thing creates a very long string ~ 10MB, and then reference it 2000 times. If there was no copy-on-write then I will need 2*10^10 memory, which is more than a process on 32bit  architecture can address.
 [2004-09-04 09:07 UTC] tomas_matousek at hotmail dot com
Of course, there is copy-on-write. 
That's a reason why reseting array inner pointer on copy is a bug.
 [2004-09-06 08:23 UTC] derick@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

This is not a bug, but a design thing.
 [2004-09-26 20:38 UTC] tomas_matousek at hotmail dot com
Wow, PHP is non-deterministic. That's cool feature.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 21:01:27 2024 UTC