Lorsque vous lancez une exception avec python (CPython), le cadre qui a levé l'exception est ajouté au cadre qui a intercepté l'exception. Cela rend le comportement du nombre de références non trivial et prolonge involontairement la durée de vie de l'objet.
class Foo(Exception):
def __init__(self):
print 'construt'
def __del__(self):
print 'destruct'
def raiseError(self):
raise Exception()
def main ():
print 'enter main'
foo = Foo()
try:
foo.raiseError()
except:
print 'catch exception'
foo = None
print 'exit main'
try:
main()
finally:
print 'finish'
La sortie du code ci-dessus est la suivante.
enter main
construt
catch exception
exit main
destruct
finish
Comme mentionné ci-dessus, même si l'objet «foo» dans «main» est destiné à être libéré avant «exit main», la durée de vie de «foo» est prolongée jusqu'à ce que la trame de «main» soit libérée.
Ceci est dû au fait que le cadre à l'intérieur de riseError
qui a levé l'exception est conservé dans le cadre à l'intérieur de main
, et le cadre à l'intérieur de riseError
contient self = foo
.
Les trames d'exception sont libérées avec sys.exc_clear ()
.
Dans un cas similaire, lors d'une tentative d'accrochage dans une boucle, le moment de libération de l'objet sécurisé dans la boucle peut être décalé d'une boucle. Cela est dû au fait que la trame d'exception est libérée par le jeté d'exception dans la boucle suivante.
http://stackoverflow.com/questions/8822418/object-not-freed-after-an-exception-raise-in-python-2-7
Recommended Posts