Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Why this ref leak?

Reply
Thread Tools

Why this ref leak?

 
 
Gerhard Häring
Guest
Posts: n/a
 
      02-27-2008
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
 
Reply With Quote
 
 
 
 
Bjoern Schliessmann
Guest
Posts: n/a
 
      02-27-2008
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.

 
Reply With Quote
 
 
 
 
Peter Otten
Guest
Posts: n/a
 
      02-27-2008
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
 
Reply With Quote
 
Thomas Heller
Guest
Posts: n/a
 
      02-27-2008
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

 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      02-27-2008
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
 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      02-27-2008
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

 
Reply With Quote
 
Bjoern Schliessmann
Guest
Posts: n/a
 
      02-27-2008
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.

 
Reply With Quote
 
Duncan Booth
Guest
Posts: n/a
 
      02-27-2008
Peter Otten <__peter__@web.de> 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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
passing ref to ptr again as ref to ptr.... osama178@gmail.com C++ 22 04-30-2008 10:42 AM
passing ref to ptr again as ref to ptr.... osama178@gmail.com C++ 6 04-29-2008 08:09 AM
passing ref to ptr again as ref to ptr.... osama178@gmail.com C++ 0 04-24-2008 08:23 PM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
strong ref from weak ref? Navindra Umanee Ruby 2 02-12-2005 05:06 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57