2010-11-04 15 views
1

J'ai ce code pour obtenir l'appelant du nom de fichier de ma fonction, le numéro de ligne, et la fonction. Il semble y avoir des fuites de cadres et je ne comprends pas pourquoi. Est-ce que ça me rejette et ma fuite doit être ailleurs?Python fuite de mémoire, fuites de cadres

 rv = "(unknown file)", 0, "(unknown function)" 

      for f in inspect.stack()[1:]: 
       if __file__ in f: 
        continue 
       else: 
        rv = f[1:4] 
        break 

     return rv 

Je ne sauvegarde nulle part une référence au cadre. Mais il est certainement des cadres qui fuient:

 
> objcallgraph.show_most_common_types() 
>tuple      24798 
>frame      9601 
>... 

Mise à jour: Mes cadres sont sans aucun doute être divulgués. J'ai fait la suggestion à propos de gc.set_debug() et les images vont très lentement dans la liste gc.garbage. Pas même près de combien sont créés bien que show dans show_most_common_types(). J'ai une question sur la portée bien que, dans ce qui précède, ne pas f sortir de la portée après la boucle for? Parce que je viens d'essayer ceci:


for f in range(20): 
    l = 1 

print f 

et 19. Ainsi imprimé pourrait-il être mon f dans la boucle pour une fuite de? Ce graphique de référence d'une référence de cadre qui était dans ma liste de gc.garbage:

alt text

Update2:

Il ressemble à lui-même le module inspecter est la tenue des références aux cadres. Ceci est un objetgraph d'une référence arrière à partir d'un cadre en direct, pas un sur la liste des déchets.

alt text

Lien here parce qu'il est trop large.

Y a-t-il un moyen d'effacer le module d'inspection? Où sont ces cadres sauvés =

+0

Que faites-vous avec le retour rv? –

+1

Que montre gc.set_debug (gc.DEBUG_LEAK)? Vous devriez voir les objets qui ont fui dans sa sortie. – dcolish

+0

Je ne savais même pas que je pouvais faire ça, je dois avoir scanné cela dans le doc. Je verrai ce que ça dit demain quand je serai de retour à mon ordinateur – Falmarri

Répondre

1

Eh bien, je pense que j'ai trouvé le problème. Il semble que ce soit un problème avec le module inspect et le code C sous-jacent dans une application multi-thread. Le module avec le code ci-dessus est importé à partir de différents threads. Et ce deuxième graphique pointe vers le problème.

alt text

Les function énumérés ici dans le 3ème nœud vers le bas est inspect.getmodule(). Je ne pouvais pas tout faire et j'ai dû faire quelques recadrages.

(Pdb) objgraph.at(3510928) 
<cell at 0x359290: dict object at 0x3849c0> 

Et à l'intérieur du dict est tous les cadres

(Pdb) objgraph.at(0x3849c0) 

    {(<frame object at 0x97a288>, '/lib/python26.zip/logging/__init__.py'): <module 'logging' from '/lib/python26.zip/logging/__init__.py'>, 
    (<frame object at 0x896288>, '/lib/python26.zip/logging/__init__.py'): <module 'logging' from '/lib/python26.zip/logging/__init__.py'>, 
    (<frame object at 0xa621b0>, '/lib/python26.zip/logging/__init__.py'): <module 'logging' from '/lib/python26.zip/logging/__init__.py'>, 
    (<frame object at 0x11266e8>, '/lib/python26.zip/logging/__init__.py'): <module 'logging' from '/lib/python26.zip/logging/__init__.py'>, 
    ...} 

Et si vous obtenez les cadres extérieurs de tous les cadres

(Pdb) inspect.getouterframes(objgraph.at(0x97a288)) 
[(<frame object at 0x97a288>, '/lib/python26.zip/logging/__init__.py', 1028, 'debug', ['   self._log(DEBUG, msg, args, **kwargs)\n'], 0), 
(<frame object at 0x794040>, '/lib/python26.zip/logging/__init__.py', 1505, 'debug', [' root.debug(*((msg,)+args), **kwargs)\n'], 0), 
(<frame object at 0x794e58>, '/mmc/src/core/controller/main.py', 1046, '__startCharge', ['   self.chargeLock.release()\n'], 0), 
(<frame object at 0x5c4260>, '/mmc/src/core/controller/main.py', 1420, 'watchScheduleStartChargeCondition', ['      ret = self.__startCharge(0, eventCode=eventCode)\n'], 0), 
(<frame object at 0x5c0dd0>, '/home/ephibian/Python2/_install/lib/python2.6/threading.py', 484, 'run', None, None), 
(<frame object at 0x5c3b48>, '/home/ephibian/Python2/_install/lib/python2.6/threading.py', 532, '__bootstrap_inner', None, None), 
(<frame object at 0x218170>, '/home/ephibian/Python2/_install/lib/python2.6/threading.py', 504, '__bootstrap', None, None)] 

Ils pointent tous à la méthode __bootstrap dans le filetage. Je pourrais être sur la mauvaise voie ici, mais le contexte de certains de ces cadres sont loin d'être la méthode que j'ai appelée.

1

EDIT Je me suis juste rendu compte que c'est faux, la référence f et f_back pointent tous les deux de la même manière. Je vais le laisser dans le cas où il inspire quelqu'un d'autre:

Chaque cadre a un pointeur f_back, donc lorsque vous définissez f = inspect.stack()[1] alors inspect.stack()[0][0].f_locals (qui contient f) a maintenant une référence à ...stack()[1] et ...stack()[1][0].f_back points ...stack()[0][0]. Vous avez donc créé une référence circulaire qui doit être résolue par GC plutôt que simplement par le nombre de références. Le GC n'est pas réglé pour gérer votre taux de création d'objets, donc vous consommez de plus en plus de mémoire.

Vous pouvez probablement éliminer la référence circulaire simplement en définissant f = None à la sortie de la fonction. Cela casse la référence circulaire.