Page 1 sur 1

Bug? de refcount (zval) dans un tableau avec les Iterators (

Posté : 13 août 2007, 12:15
par titerm
Suite a un pb que j'avais évoqué ici,
j 'ai finalement upgradé mon serveur en 5.2.3 et mon pb concernant les références sur des tableaux a bien été résolu.
Néanmoins, il m'en reste un que je ne m'explique toujours pas et je n'ai pas trouvé de bug qui pourrait référencer ce pb.

Voila un bout de code pour reproduire le pb
$levels = array("l1","l2","l3"); // 3 niveaux 
$arr2['one']['two'] = 'ORG';    // Un tableau de base
foreach($levels as $v) {
	$arr[$v] = $arr2;
}
unset($arr2);    // Suppression du tableau de base
echo "<pre>";  // Affiche propreprement les dump
debug_zval_dump($arr);
// Brise artificielement le refcount
$arr['l2']['one']['two'] = $arr['l2']['one']['two'];
echo "<hr>";
debug_zval_dump($arr);

foreach($levels as $level) {
	 // Pour chaque feuille
	$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr[$level]));
	foreach($iterator as $leaf) {
		$iterator->offSetSet($iterator->key(), $level ); // Update la feuille avec le level
	}
}
echo "<hr>";
debug_zval_dump($arr);
Et la sortie

Ici, on a bien un refcount de 3 pour le tableau de base qui a été affecté a chq level (donc 3 fois)

Code : Tout sélectionner

array(3) refcount(2){ ["l1"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(1) } } ["l2"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(1) } } ["l3"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(1) } } }
// Suite a l'affectation bidon du level2, on casse bien un refcount et on a un refcount de 2 pour le leveal 1 et 3

Code : Tout sélectionner

array(3) refcount(2){ ["l1"]=> array(1) refcount(2){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(2) } } ["l2"]=> array(1) refcount(1){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(2) } } ["l3"]=> array(1) refcount(2){ ["one"]=> array(1) refcount(1){ ["two"]=> string(3) "ORG" refcount(2) } } }
Et c'est la que ca se gate, on se rend compte que lorsque que l'on passe par un iterateur, le refcount n'est pas brisé et le level 1 et level 3 sont mis a jours comme si ils étaient des références, hors on voit bien ds le dump qu'il n'y a aucune reference (elles apparaissent avec un & avant le mot clé array quane il y en a une), le level2 est ok car le refcount est brisé dans l'étape précédente

Code : Tout sélectionner

array(3) refcount(2){ ["l1"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(2) "l3" refcount(4) } } ["l2"]=> array(1) refcount(1){ ["one"]=> array(1) refcount(1){ ["two"]=> string(2) "l2" refcount(2) } } ["l3"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(2) "l3" refcount(4) } } }
Et voila ce que je m'attendais a obtenir...

Code : Tout sélectionner

array(3) refcount(2){ ["l1"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(2) "l1" refcount(4) } } ["l2"]=> array(1) refcount(1){ ["one"]=> array(1) refcount(1){ ["two"]=> string(2) "l2" refcount(2) } } ["l3"]=> array(1) refcount(3){ ["one"]=> array(1) refcount(1){ ["two"]=> string(2) "l3" refcount(4) } } }
Si quelqu'un a une idée

Posté : 16 août 2007, 15:54
par titerm
J'ai simplifié le code reproduisant mon pb.
$data['one'] = 'ORG';
$arr = array (
	'branch1' => $data,
	'branch2' => $data,
);
$iterator = new ArrayIterator($arr['branch1']);;
$iterator->offSetSet($iterator->key(), 'ALTER' );
var_dump($arr);

et mon résultat actuel

Code : Tout sélectionner

array 'branch1' => array 'one' => string 'ALTER' (length=5) 'branch2' => array 'one' => string 'ALTER' (length=5)

Est-ce que quelqu'un peut me dire si il a un résultat identique ?