Why this ref leak?

Discussion in 'Python' started by Gerhard Häring, Feb 27, 2008.

  1. import sys

    def foo():
    class C(object):
    pass

    foo()
    print ">>", sys.gettotalrefcount()
    foo()
    print ">>", sys.gettotalrefcount()
    foo()
    print ">>", sys.gettotalrefcount()

    >> 21366
    >> 21387
    >> 21408

    [9779 refs]

    Both Python 2.4 and 2.5 don't clean up properly here. Why is this?
    Aren't classes supposed to be garbage-collected?

    -- Gerhard
     
    Gerhard Häring, Feb 27, 2008
    #1
    1. Advertising

  2. Gerhard Häring wrote:

    > Both Python 2.4 and 2.5 don't clean up properly here. Why is this?
    > Aren't classes supposed to be garbage-collected?


    Yes, but not neccessarily immediately.

    BTW, where is your method sys.gettotalrefcount supposed to come
    from? My CPython doesn't have it.

    Regards,


    Björn

    --
    BOFH excuse #219:

    Recursivity. Call back if it happens again.
     
    Bjoern Schliessmann, Feb 27, 2008
    #2
    1. Advertising

  3. Gerhard Häring

    Peter Otten Guest

    Gerhard Häring wrote:

    > import sys
    >
    > def foo():
    > class C(object):
    > pass
    >
    > foo()
    > print ">>", sys.gettotalrefcount()
    > foo()
    > print ">>", sys.gettotalrefcount()
    > foo()
    > print ">>", sys.gettotalrefcount()
    >
    > >> 21366
    > >> 21387
    > >> 21408

    > [9779 refs]
    >
    > Both Python 2.4 and 2.5 don't clean up properly here. Why is this?
    > Aren't classes supposed to be garbage-collected?


    The reference keeping the classes alive is probably object.__subclasses__():

    >>> class A(object): pass

    ....
    >>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    1
    >>> class A(object): pass

    ....
    >>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    2

    Peter
     
    Peter Otten, Feb 27, 2008
    #3
  4. Gerhard Häring schrieb:
    > import sys
    >
    > def foo():
    > class C(object):
    > pass
    >
    > foo()
    > print ">>", sys.gettotalrefcount()
    > foo()
    > print ">>", sys.gettotalrefcount()
    > foo()
    > print ">>", sys.gettotalrefcount()
    >
    > >> 21366
    > >> 21387
    > >> 21408

    > [9779 refs]
    >
    > Both Python 2.4 and 2.5 don't clean up properly here. Why is this?
    > Aren't classes supposed to be garbage-collected?
    >
    > -- Gerhard


    Replace "foo()" with "foo(); gc.collect()" and the refcounts are stable.
    Tested the python 2.6 from trunk.

    Thomas
     
    Thomas Heller, Feb 27, 2008
    #4
  5. Gerhard Häring

    Peter Otten Guest

    Peter Otten wrote:

    >> Both Python 2.4 and 2.5 don't clean up properly here. Why is this?
    >> Aren't classes supposed to be garbage-collected?

    >
    > The reference keeping the classes alive is probably
    > object.__subclasses__():
    >
    >>>> class A(object): pass

    > ...
    >>>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    > 1
    >>>> class A(object): pass

    > ...
    >>>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    > 2


    Oops, wrong guess:

    >>> import gc
    >>> gc.collect()

    6
    >>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    1

    Peter
     
    Peter Otten, Feb 27, 2008
    #5
  6. Gerhard Häring

    Peter Otten Guest

    Bjoern Schliessmann wrote:

    > BTW, where is your method sys.gettotalrefcount supposed to come
    > from? My CPython doesn't have it.


    It's in the debug build only.

    Peter
     
    Peter Otten, Feb 27, 2008
    #6
  7. Peter Otten wrote:
    > Bjoern Schliessmann wrote:


    >> BTW, where is your method sys.gettotalrefcount supposed to come
    >> from? My CPython doesn't have it.

    >
    > It's in the debug build only.


    Makes sense; thank you.

    Regards,


    Björn

    --
    BOFH excuse #292:

    We ran out of dial tone and we're and waiting for the phone company
    to deliver another bottle.
     
    Bjoern Schliessmann, Feb 27, 2008
    #7
  8. Gerhard Häring

    Duncan Booth Guest

    Peter Otten <> wrote:

    > Peter Otten wrote:
    >
    >>> Both Python 2.4 and 2.5 don't clean up properly here. Why is this?
    >>> Aren't classes supposed to be garbage-collected?

    >>
    >> The reference keeping the classes alive is probably
    >> object.__subclasses__():
    >>
    >>>>> class A(object): pass

    >> ...
    >>>>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    >> 1
    >>>>> class A(object): pass

    >> ...
    >>>>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    >> 2

    >
    > Oops, wrong guess:
    >
    >>>> import gc
    >>>> gc.collect()

    > 6
    >>>> sum(1 for c in object.__subclasses__() if c.__name__ == "A")

    > 1
    >

    The list of subclasses is stored using weak references: that's why you have
    to call a method to create a real list. What actually stops the class just
    vapourising is its __mro__ attribute which creates a cycle, but the garbage
    collector clears that up as you saw.
     
    Duncan Booth, Feb 27, 2008
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,990
    Smokey Grindel
    Dec 2, 2006
  2. Replies:
    0
    Views:
    341
  3. Replies:
    22
    Views:
    762
    peter koch
    Apr 30, 2008
  4. Replies:
    6
    Views:
    352
    James Kanze
    Apr 29, 2008
  5. Navindra Umanee

    strong ref from weak ref?

    Navindra Umanee, Feb 12, 2005, in forum: Ruby
    Replies:
    2
    Views:
    145
    Navindra Umanee
    Feb 12, 2005
Loading...

Share This Page