Search This Blog

Monday, June 15, 2009

Python Memory Leak (Circular Reference)

In short, one name, two (reference) counts.
So if you delete the name (also subtract the reference by one), you still have one reference.
(thus memory is not garbage collect)

e.g. you have a name to call a book, the book contains a reference to itself. (two references)
later you delete the name, you still have one reference (but you can't touch because no name!)

a = []
b = []

a.append(b)
b.append(a)

#now we are done with a, and b, try to delete them
del a
#a stays alive(a's reference count does not drop to zero, b still has one reference to a)
#Python says,"I cannot free you because b is still alive and using you, stay there."

del b
#b stays alive(b's reference count does not drop to zero, a still has one reference to b)
#Python says,"I cannot free you because a is still alive and using you, stay there."

Now, we cannot use a, and b because both names are unavailable (we can't free it manually), each with 1 reference count (the garbage collector can't free it)

#HOW TO SOLVE THIS?  Just break the circular dependency, for example, set
a[0] = None

more
http://blogs.infoecho.net/echo/2007/06/24/circular-references-in-python/

The following code create circular references in python:

>>> aRef = [] >>> aRef.append(aRef) >>> print aRef [[...]]

This creates a list object referred by a variable named “aRef”. the first element in the list object is a reference to itself. In this case, the “del aRef” dereference aRef to the list object. However, the reference count of the list object does not decrease to zero and the list object is not garbage collected, since the list object still refers to itself. In this case, the garbage collector in Python will periodically check if such circular references exist and the interpreter will collect them. The following is an example to manually collect the space used by circular referenced objects.

>>> import gc >>> gc.collect() 0 >>> del aRef >>> gc.collect() 1 >>> gc.collect() 0


No comments: