Bonjour à tous !

Je viens partager une observation faite sur la façon dont PHP (5.2) alloue la mémoire du serveur aux objets au sein d'une boucle.

Voici grossièrement la structure de la boucle :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
 
foreach($pdo_stmt as $pdo_row)
{
	$oObject = new ObjetX();
        $oObject->init($pdo_row);
 
        $pdo->exec(.....);
}
Au delà de 1000 traitements à effectués, la limite de mémoire de 32 Mo à été atteinte, alors qu'il n'y a aucun cumul de variable ou de quoi que ce soit, je précise que j'ai pris soin de définir un destructeur au sein de l'objet, qui réinitialise bien toutes ses propriétés.
L'objet n'est stocké nulle part ailleurs qu'au sein de la boucle (aucun enregistrement dans une classe Singleton par ex).
Il s'avère en faite que le destructeur n'était pas appelé, et ce même en ajoutant les lignes :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
 
unset($oObj);
$oObj=NULL;
C'est comme si chaque objet initialisé était conservé en mémoire alors que la variable est réinitialisée à chaque boucle et que le destructeur devrait être normalement appelé.
Est-ce que vous trouvez que c'est un comportement normal ? Qu'un détail m'échappe ?

Bref, il a fallu que j'appelle explicitement le destructeur pour que la mémoire soit libérée après exécution de la boucle.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 
$oObj->__destruct();
Si vous avez des avis ou des expériences à faire part la dessus je suis preneur !

EDIT : Après certaines recherches il s'agit d'un bug connu, celui des références cycliques qui empêchent le Garbage Collector de fonctionner normalement. (On ne le voit pas dans mon exemple car j'ai simplifié le code pensant que ça n'influerai en rien...comme quoi !)
Ci-joint quelques liens bien utiles :
http://blog.pascal-martin.fr/post/ph...oire#exemple-1
http://paul-m-jones.com/archives/262