Understanding gc.get_referrers

2019-06-17 05:22发布

问题:

I'm trying to track a memory leak in Python (2.7). I've found gc.get_referrers, but don't understand the output. After deleting dying_node (which should get rid of all references except for a list that I've created as part of my hunting), I have in my code:

gc.collect()
print "done dying: ", getrefcount(dying_node) #note, includes the reference from getrefcount
referrers = gc.get_referrers(dying_node)
print "referrers: "
for referrer in referrers:
    print referrer

which yields the output:

> done dying:   4
> referrers: 
> [<__main__.Node instance at 0x104e53cb0>, <__main__.Node instance at 0x104e53b90>, <__main__.Node instance at 0x104e53b00>, <__main__.Node instance at 0x104e53d40>, <__main__.Node instance at 0x104e53ab8>, <__main__.Node instance at 0x104e53bd8>, <__main__.Node instance at 0x104e53a70>, <__main__.Node instance at 0x104e53c20>, <__main__.Node instance at 0x104e53c68>, <__main__.Node instance at 0x104e53b48>]
> [<__main__.Node instance at 0x104e53c20>, <__main__.Node instance at 0x104e53ab8>, <__main__.Node instance at 0x104e53c68>, <__main__.Node instance at 0x104e53a70>, <__main__.Node instance at 0x104e53cb0>, <__main__.Node instance at 0x104e53b00>, <__main__.Node instance at 0x104e53d40>, <__main__.Node instance at 0x104e53b90>, <__main__.Node instance at 0x104e53b48>, <__main__.Node instance at 0x104e53bd8>]
> <frame object at 0x104516300>

I think this means I have two lists of Nodes which refer to this node and a frame object. I assume the frame object is the name dying_node that I'm looking at. One of the lists would be a list I've created to help me in my hunting. But is there a way to figure out what the other list would be?

回答1:

Alright, so an answer is

def namestr(obj, namespace):
    return [name for name in namespace if namespace[name] is obj]

Example:

gc.collect() #make sure all garbage cleared before collecting referrers.
referrers = gc.get_referrers(object_of_interest)
for referrer in referrers:
    print namestr(referrer, globals())

or if it's local:

    print namestr(referrer, locals())

This will print something like ['referrer', 'name_Im_interested_in']. The 'referrer' is because of the fact I've just named it that. The other thing in the list is what I'm trying to find.

I borrowed this from an answer here. If anyone has a better answer, please post it and I'll be happy to accept it.