LoginSignup
1
0

More than 5 years have passed since last update.

[python, CPython] 例外を投げた際のGCの挙動

Posted at

python(CPython)で例外を投げると、例外を投げたフレームが例外をキャッチしたフレームに追加される。
このため、リファレンスカウントの動作が非自明になり、オブジェクトの寿命が意図せず延長される。

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'

以上のコードの出力は以下のようになる。

enter main
construt
catch exception
exit main
destruct
finish

以上のように、main内のfooオブジェクトを'exit main'の前に解放する事を意図したとしてもmainのフレームが解放されるまでfooの寿命が延長される。
これは、例外を投げたraiseError内のフレームが、main内のフレームに保持され、raiseError内のフレームはself = fooを保持しているためだ。

例外フレームの解放はsys.exc_clear()で行う。

似たようの事例としては、ループ内でtry-catchしている時に、ループ内で確保したオブジェクトの解放のタイミングが1ループ分ずれる等があり得る。
これは例外フレームが次のループでの例外スローによって解放されるからだ。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0