Почему деструктор называется, когда Cpython Collector отключен?

StackOverflow https://stackoverflow.com/questions/2578098

Вопрос

Я пытаюсь понять внутренние годы CPYPHON COLLECTER мусора, в частности, когда вызывается деструктор. До сих пор поведение интуитивно понятно, но в следующих случаях поезжает меня:

  1. Отключить GC.
  2. Создайте объект, затем удалите ссылку на него.
  3. Объект разрушен, а метод _____Del_____ вызывается.

Я думал, что это произойдет, только если сборщик мусора был включен. Может кто-нибудь объяснить, почему это происходит? Есть ли способ отложить звонить в деструктор?

import gc
import unittest

_destroyed = False

class MyClass(object):

    def __del__(self):
        global _destroyed
        _destroyed = True

class GarbageCollectionTest(unittest.TestCase):

    def testExplicitGarbageCollection(self):
        gc.disable()
        ref = MyClass()
        ref = None
        # The next test fails. 
        # The object is automatically destroyed even with the collector turned off.
        self.assertFalse(_destroyed) 
        gc.collect()
        self.assertTrue(_destroyed)

if __name__=='__main__':
    unittest.main()

Отказ от ответственности: Этот код не предназначен для производства - я уже отметил, что это очень конкретно для реализации и не работает на Jython.

Это было полезно?

Решение

Python имеет оба Отсчет ссылки Коллекция мусора и циклический сбор мусора, и это последний, что gc Модульные элементы управления. Присвоение ссылки не может быть отключено, и, следовательно, все еще происходит, когда циклический сборщик мусора выключен.

Так как нет никаких ссылок на ваш объект после ref = None, это __del__ Метод называется в результате его ссылочного отчета до нуля.

В Документация: «С коллекционера добавки Присвоение ссылки уже использовалось в Python ... »(мой акцент).

Вы можете остановить первое утверждение от стрельбы, сделав объект относительно самого себя, так что его ссылочный счетчик не переходит на ноль, например, придавая ему этот конструктор:

def __init__(self):
    self.myself = self

Но если вы это сделаете, второе утверждение будет огонь. Это потому, что цикловы мусора с __del__ Методы не собираются - см. Документацию для gc.grag.

Другие советы

В зависимости от вашего определения сборщика мусора, CPYthon имеет два мусорных коллекторов, ссылаться, подсчитав одну, а другой.
Справочный счетчик всегда работает, и не может быть выключен, так как довольно быстрый и легкий, который не сильно не влияет на время выполнения системы.
Другой (какой-то вариант метки и развертки, я думаю), проходит каждый так часто и может быть отключен. Это связано с тем, что он требует, чтобы переводчик был приостановлен, пока он работает, и это может произойти в неверном моменте, и потреблять довольно много времени процессора.
Эта способность отключить ее в течение тех пор, когда вы ожидаете делать то, что это важно, и отсутствие этого GC не заставит вас никаких проблем.

Документы здесь Объясните, как называется «дополнительный сборщик мусора» на самом деле является коллектором циклический Мусор (тот, который считает ссылочный счет, не поймал). Ссылочный счет объясняется здесь, с кивком до его взаимодействия с циклическим GC:

В то время как Python использует традиционную реализацию отсчета ссылок, он также предлагает детектор цикла, который работает для обнаружения ориентированных циклов. Это позволяет приложениям не беспокоиться о создании прямых или косвенных круговых ссылок; Это слабость сборника мусора, реализованного, используя только ссылку. Опорные циклы состоят из объектов, которые содержат (возможно, непрямые) ссылки на себя, так что каждый объект в цикле имеет ссылочный счет, который не равен нулю. Типичные реализации отсчета о обращении не могут восстанавливать память, принадлежащую к любым объектам в ориентирном цикле или упоминаются от объектов в цикле, даже если нет дальнейших ссылок на сам цикл.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top