2015-03-02 3 views
0

Во время разработки проекта, над которым я работал, я работал над проблемой, с которой я столкнулся с проблемой сборщика мусора, неспособного де-выделить связанные списки или даже списки.Сборщик мусора не освобождает связанные объекты (Linked Lists memory leak)

class B(object): 
    def __init__(self, previous): 
     self.previous = previous 
    def __del__(self): 
     self.previous = None 
     self = None 
import gc 
gc.set_debug(gc.DEBUG_LEAK) 
l = [] 
prev = None 
for i in range(1000000): 
    b = B(prev) 
    l.append(b) 
    prev = b 

del l[:] 
gc.collect() 
print gc.garbage 

Когда я проверяю использование памяти перед распределением и после выделения и после удаления. Использование памяти после распределения по-прежнему совпадает с использованием памяти после удаления. и сборщик мусора не жалуется на утечки памяти.

Когда я использую pympler для отслеживания объектов в среде python. объекты не существуют, но для них выделена память.

Однако эта проблема возникает только тогда, когда экземпляры связаны. Если экземпляры не имеют ссылки на другие. Сборщик мусора ведет себя нормально.

Любая идея, почему?

+1

В приведенном выше коде после 'del l [:]' ваш полный список по-прежнему доступен через ссылки 'b' и' prev'. – sebastian

ответ

2

Возможно, вы очистили l, но b и prev все еще ссылаются на последние B экземпляр создан. В свою очередь, этот экземпляр относится к предыдущему примеру, созданной и т.д. сохраняя всю цепочку живых:

>>> class B(object): 
...  def __init__(self, previous): 
...   self.previous = previous 
...  def __del__(self): 
...   self.previous = None 
...   self = None 
... 
>>> l = [] 
>>> prev = None 
>>> for i in range(1000000): 
...  b = B(prev) 
...  l.append(b) 
...  prev = b 
... 
>>> del l[:] 
>>> prev 
<__main__.B object at 0x11f269d50> 
>>> b 
<__main__.B object at 0x11f269d50> 
>>> b.previous 
<__main__.B object at 0x11f269d10> 
>>> import gc 
>>> sum(1 for ob in gc.get_objects() if isinstance(ob, B)) 
1000000 
>>> del b, prev 
>>> sum(1 for ob in gc.get_objects() if isinstance(ob, B)) 
0 

gc.garbage список будет только когда-либо список B экземпляров если есть круговой ссылка; например если последний экземпляр B в цепочке ссылается на другой экземпляр в той же цепочке, а не на None.

+0

Большое спасибо, rookie error =/ –

+0

Что-нибудь еще не хватает? Вы снова приняли его снова. –

+0

На самом деле, я рассмотрел концепцию И это прекрасно и правильно. Однако, когда я попытался использовать память, уменьшенную на несколько мегабайт, тем не менее, все еще имея 300mgbs памяти, выделенной ни для чего. –

Смежные вопросы