Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why appending list to itself, and then deleting, results in memory leak

I found this memory leak detection snippet and was wondering about the memory leak it generated.

import gc

def dump_garbage():
    """
    show us what's the garbage about
    """

    # force collection
    print("\nGARBAGE:")
    gc.collect()

    print("\nGARBAGE OBJECTS:")
    for x in gc.garbage:
        s = str(x)
        if len(s) > 80: s = s[:80]
        print(type(x),"\n  ", s)

if __name__=="__main__":
    import gc
    gc.enable()
    gc.set_debug(gc.DEBUG_LEAK)

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

    # show the dirt ;-)
    dump_garbage()

In order to test the gc memory leak detection, the author created its own little mem leak:

l = []
l.append(l)
del(l)

Why would that result in a leak? As I see it, I would have a list object, and than a nested list object, where the inner is the outer, and than delete the outer. Wouldn't the gc know to delete all references to the original list and thus result in a leaked inner list?

like image 934
CIsForCookies Avatar asked Nov 26 '22 17:11

CIsForCookies


1 Answers

(Editing my earlier comments into an answer.)

The linked article is from 2001. Back in those days, Python 2.x was new, and many people were probably still using Python 1.x.

Python 1.x relied solely on reference counting for garbage collection, and cyclic references are the textbook example of when that fails. Python 2.x added a cycle detection step, but there were some remaining wrinkles, such as the presence of a __del__ method blocking the garbage collector, because it could not figure out the proper order of destruction. As of Python 3.4, most of the wrinkles have been ironed out.

So why does the example code still indicate leaks? It sets the GC_DEBUG_LEAK flag which, among other things, explicitly tells the garbage collector to keep unreachable objects around!

like image 52
Ture Pålsson Avatar answered Jan 04 '23 23:01

Ture Pålsson