Why is this a mem leak?

S

Steve

Hi,

I saw an article online
(http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65333) where it
explains how one can find out if there's a memory leak in ones program.
How is there a memory leak in this:

# make a leak
l = []
l.append(l)
del l

??? Shouldn't deleting an object explicitly give the GC a better chance
to find the object? Won't deleting it cause it's reference to go down
(another question: which GC is python 2.3 using? Refcount or
Generational?). Isn't 'del' similar to 'free'ing in C??

Thanks,

Steve
 
S

Steve

Steve said:
Hi,

I saw an article online
(http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65333) where it
explains how one can find out if there's a memory leak in ones program.
How is there a memory leak in this:

# make a leak
l = []
l.append(l)
del l

??? Shouldn't deleting an object explicitly give the GC a better chance
to find the object? Won't deleting it cause it's reference to go down
(another question: which GC is python 2.3 using? Refcount or
Generational?). Isn't 'del' similar to 'free'ing in C??

Thanks,

Steve

Another question:

I get the following when I set DEBUG in gc to DEBUG_LEAK:

GARBAGE:
gc: uncollectable <JCollector instance at 0x403a7f2c>
gc: uncollectable <NCollector instance at 0x403fa2cc>
gc: uncollectable <dict 0x403a9c64>
gc: uncollectable <dict 0x403f9934>
gc: uncollectable <instancemethod 0x403a5dec>
gc: uncollectable <instancemethod 0x403aa0f4>

this was after calling a method foo() which created two instances of a
single class, which then created the dictionaries and instancemethods
named above. After foo() ended, I would have thought that these
instances/objects would have been collected. I called gc.collect()
explicitly two times but the gc.garbage list still held the same list as
'garbage'. Does 'uncollectable' here means that these objects will never
be collected? Why is that? They're not bound by anything once foo()
exits. How can I make sure the memory allocated for this junk is deleted
(since I want to run foo() in a loop). Can someone please tell me what's
happening? Thanks,

Steve
 
J

jepler

(The below message confuses Python, the language, with the CPython 2.3
implementation)

In the absence of gc, l will never be collected. (well, "the thing l once
named", since it won't name anything directly after the "del" statement)

with cyclic GC plus refcounting, including Python 2.3 when built in the
default way, l will be collected.

"del l" has the effect of making the name "l" no longer refer to anything
and of decreasing the reference count of that object by 1. It does not
relate directly to C's free() or C++'s delete, because those release
the storage underlying the object, even if pointers to that object still
exist elsewhere in the program. CPython only releases the underlying
storage for the object when the refcount reaches 0, with "GC" being used
to find unreachable cycles and deal with them in some other way.

Jeff
 
T

Tim Peters

[Steve said:
Another question:

I get the following when I set DEBUG in gc to DEBUG_LEAK:

GARBAGE:
gc: uncollectable <JCollector instance at 0x403a7f2c>
gc: uncollectable <NCollector instance at 0x403fa2cc>
gc: uncollectable <dict 0x403a9c64>
gc: uncollectable <dict 0x403f9934>
gc: uncollectable <instancemethod 0x403a5dec>
gc: uncollectable <instancemethod 0x403aa0f4>

this was after calling a method foo() which created two instances of a
single class, which then created the dictionaries and instancemethods
named above. After foo() ended, I would have thought that these
instances/objects would have been collected. I called gc.collect()
explicitly two times but the gc.garbage list still held the same list as
'garbage'. Does 'uncollectable' here means that these objects will never
be collected?

No, but it does mean it's very likely they'll never be collected --
unless you do something to make them collectable.
Why is that?

The gc module is documented in the Library Reference Manual. The docs
for gc.garbage there should answer all your questions here.
They're not bound by anything once foo() exits.
How can I make sure the memory allocated for this junk is deleted
(since I want to run foo() in a loop).

Read the gc.garbage docs. Then don't create cycles containing objects
with __del__ methods, or, if you think you must, do what the docs say
to do <wink>.
 
M

Mel Wilson

I saw an article online
(http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65333) where it
explains how one can find out if there's a memory leak in ones program.
How is there a memory leak in this:

# make a leak
l = []
1 reference to the new list, in the namespace
under 'l'. Reference count == 1
l.append(l)
1 more reference to the list, in its own
[0] element. Reference count == 2
The reference in the namespace is removed.
Reference count = 1
??? Shouldn't deleting an object explicitly give the GC a better chance
to find the object? Won't deleting it cause it's reference to go down
(another question: which GC is python 2.3 using? Refcount or
Generational?). Isn't 'del' similar to 'free'ing in C??

Not really. `del` removes a reference, which usually
culminates in freeing the storage, after all the required
dels are done.

For no memory leak:

l = [] # ref count = 1, i.e. l
l.append (l) # ref count = 2, i.e. l and :itself:[0]
m = l # ref count = 3, i.e. l, :itself:[0] and m
del l # ref count = 2, i.e. :itself:[0] and m
del m[0] # ref count = 1, i.e. m
del m # ref count = 0, and the objects space can be collected

(Here :itself: is made-up language, no way a valid Python
identifier, but how else to discuss a reference that isn't
part of any namespace?)

Regards. Mel.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top