|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2007-08-16 08:18 UTC] titerm at lfdj dot com
Description:
------------
When multiple entries of an array are initialized with a $base var array, new entries will increase refcount.
Any modification of this new entries should decrease refcount.
But if modification are done through a recursive Array Iterator, refcount works like it was reference, and all leaf are modified
Reproduce code:
---------------
// Reference var array
$base['one']['two'] = 'ORG';
// Work array
$arr = array (
'l1' => $base,
'l2' => $base,
'l3' => $base,
);
unset($base); // No need anymore of reference
// Break refcount for level 2, level 1 and level 3 are still refcount
$arr['l2']['one']['two'] = $arr['l2']['one']['two'];
// Create an iterator on level 1
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr['l1']));
// Alter leaf of level 1
$iterator->offSetSet($iterator->key(), 'ALTER' );
debug_zval_dump($arr);
Expected result:
----------------
array(3) refcount(2){
["l1"]=>
array(1) refcount(1){
["one"]=>
string(5) "ALTER" refcount(1)
}
["l2"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(3) "ORG" refcount(1)
}
}
["l3"]=>
array(1) refcount(1){
["one"]=>
string(3) "ORG" refcount(1)
}
}
Actual result:
--------------
array(3) refcount(2){
["l1"]=>
array(1) refcount(3){
["one"]=>
string(5) "ALTER" refcount(1)
}
["l2"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(3) "ORG" refcount(1)
}
}
["l3"]=>
array(1) refcount(3){
["one"]=>
string(5) "ALTER" refcount(1)
}
}
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Dec 01 17:00:01 2025 UTC |
I have simplified the reproduce code to much. Sorry it should be $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr['l1'])); foreach($iterator as $leaf) { $iterator->offSetSet($iterator->key(), 'ALTER' ); } Expected result array(3) refcount(2){ ["l1"]=> array(1) refcount(1){ ["one"]=> array(1) refcount(1){ ["two"]=> string(5) "ALTER" refcount(1) } } ["l2"]=> array(1) refcount(1){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(2) } } ["l3"]=> array(1) refcount(1){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(1) } } } Actual Result array(3) refcount(2){ ["l1"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(5) "ALTER" refcount(1) } } ["l2"]=> array(1) refcount(1){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(2) } } ["l3"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(5) "ALTER" refcount(1) } } }Create a ArrayIterator on branch1. Alter the leaf by using iterator. Leave on branch2 are affected too. Simplified reproduce code. $data['one'] = 'ORG'; $arr = array ( 'branch1' => $data, 'branch2' => $data, ); $iterator = new ArrayIterator($arr['branch1']);; $iterator->offSetSet($iterator->key(), 'ALTER' ); var_dump($arr); Expected result array 'branch1' => array 'one' => string 'ALTER' (length=5) 'branch2' => array 'one' => string 'ORG' (length=3) Actual result array 'branch1' => array 'one' => string 'ALTER' (length=5) 'branch2' => array 'one' => string 'ALTER' (length=5)Since the iterator does not modify original array, this is the expected result of your script (and what I get using latest CVS build): array(2) { ["branch1"]=> array(1) { ["one"]=> string(3) "ORG" } ["branch2"]=> array(1) { ["one"]=> string(3) "ORG" } }I finally download snap. This snapshot was automatically generated on Fri, 17 Aug 2007 00:08:51 -0400 Version: 5.2.4RC3-dev Branch: HEAD Build: Release_TS The bug is still there. Take a look to the added dump of $data. $data is altered to. This can't be the expected result. $data is never used as reference. Reproduce code $data[] = 'ORG'; $arr1 = array ('branch1' => $data, 'branch2' => $data); $iterator = new ArrayIterator($arr1['branch1']);; $iterator->offSetSet($iterator->key(), 'ALTER' ); var_dump($arr1); var_dump($data); Actual result. array(2) { ["branch1"]=> array(1) { [0]=> string(5) "ALTER" } ["branch2"]=> array(1) { [0]=> string(5) "ALTER" } } array(1) { [0]=> string(5) "ALTER" }