Why is this a mem leak?

Discussion in 'Python' started by Steve, Jul 22, 2004.

  1. Steve

    Steve Guest

    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
     
    Steve, Jul 22, 2004
    #1
    1. Advertising

  2. Steve

    Steve Guest

    Steve wrote:
    > 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
     
    Steve, Jul 23, 2004
    #2
    1. Advertising

  3. Steve

    Guest

    (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
     
    , Jul 23, 2004
    #3
  4. Steve

    Tim Peters Guest

    [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?


    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>.
     
    Tim Peters, Jul 23, 2004
    #4
  5. Steve

    Mel Wilson Guest

    In article <410044cb$>, Steve <> wrote:
    >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
    > del l

    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.
     
    Mel Wilson, Jul 23, 2004
    #5
    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. Steffen Krippner
    Replies:
    0
    Views:
    280
    Steffen Krippner
    Nov 14, 2003
  2. Steffen Krippner
    Replies:
    0
    Views:
    363
    Steffen Krippner
    Nov 14, 2003
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,255
    Smokey Grindel
    Dec 2, 2006
  4. Replies:
    8
    Views:
    339
    jaysome
    Mar 1, 2007
  5. news.aon.at
    Replies:
    11
    Views:
    678
    Ian Collins
    Jan 29, 2011
Loading...

Share This Page