2012-06-09 5 views
26

Я пытаюсь понять, как сборщик мусора Python обнаруживает круговые ссылки. Когда я смотрю на документацию, все, что я вижу, это утверждение о том, что обнаружены циклические ссылки, за исключением случаев, когда задействованные объекты имеют метод __del__.Как сборщик мусора Python обнаруживает циркулярные ссылки?

Если это произойдет, мое понимание (возможно, ошибочное) состоит в том, что модуль gc действует как отказоустойчивый (я предполагаю), проходя через всю выделенную память и освобождая любые недоступные блоки.

Как Python обнаруживает & бесплатные ссылки на циркулярную память перед использованием модуля gc?

+0

»..но _выключена_ гарантируется для сбора мусора, содержащего циклические ссылки «. Скажите [docs] (http://docs.python.org/reference/datamodel.html). –

+0

Вы можете связать страницу с документацией, на которую вы ссылаетесь? –

+0

Вот страница, которую я читал: http://docs.python.org/extending/extending.html#reference-counts – user1245262

ответ

5

Я думаю, что я нашел ответ, я искал в некоторых ссылок, предоставляемых @SvenMarnich в комментариях к первоначальному вопросу:

Контейнерные объекты являются объектами Python, которые могут содержать ссылки на другие объекты Python. Списки, классы, кортежи и т. Д. Являются контейнерами; Целые числа, строки и т. Д. - нет. Таким образом, только объекты контейнера подвергаются риску оказаться в круговой ссылке.

Каждый объект Python имеет поле - * gc_ref *, которое (я считаю) установлено равным NULL для объектов, не связанных с контейнером. Для контейнерных объектов он устанавливается равным количество , не контейнер объектов, которые ссылаются на него

Любой объект контейнер с * gc_ref * подсчитывать больше 1 (? Я бы подумал, 0, но нормально сейчас?) имеет ссылки, которые не являются объектами контейнера. Таким образом, они достижимы и удалены из рассмотрения того, что они являются недоступными островами памяти.

Любой объект-контейнер, доступный объекту, который, как известно, доступен (т. Е. Те, которые мы только что признали имеющими * gc_ref * count больше 1), также не нуждаются в освобождении.

Остальные объекты контейнера недоступны (кроме друг друга) и должны быть освобождены.

http://www.arctrix.com/nas/python/gc/ является ссылка обеспечивает более полное объяснение http://hg.python.org/cpython/file/2059910e7d76/Modules/gcmodule.c найти ссылку на исходный код, который имеет комментарии далее поясняющие мысли, лежащие в основе обнаружения круговой опорной

+0

Я полагаю, что мое предпочтение в этом ответе очень своеобразно, но ссылки @SvenMarnich предоставили мне ответ в терминах, которые я мог легко понять и объяснить кому-то еще. Объяснение, данное Дэвидом Волевером, также было довольно хорошим, и если я хочу изменить/изменить или мусор собирать объекты, которые я создаю и внедряю на C, это будет очень полезно. – user1245262

22

Как Python обнаруживает & бесплатные ссылки на циркулярную память перед использованием модуля gc?

Это не так. Gc существует только до обнаружение и бесплатные циркулярные ссылки. Некруглые ссылки обрабатываются путем пересчета.

Теперь, чтобы увидеть, как дс определяет набор объектов, на которые ссылается любого объекта, посмотрите на gc_get_references функции в Modules/gcmodule.c. Соответствующий бит:

// Where `obj` is the object who's references we want to find 
traverseproc traverse; 
if (! PyObject_IS_GC(obj)) 
    continue; 
traverse = Py_TYPE(obj)->tp_traverse; 
if (! traverse) 
    continue; 
if (traverse(obj, (visitproc)referentsvisit, result)) { 
    Py_DECREF(result); 
    return NULL; 
} 

Основная функция здесь tp_traverse. Каждый тип уровня С определяет функцию tp_traverse (или в случае объектов, которые не содержат никаких ссылок, например str, устанавливает ее в NULL). Одним из примеров являются tp_traverselist_traverse, функция обхода для list:

static int 
list_traverse(PyListObject *o, visitproc visit, void *arg) 
{ 
    Py_ssize_t i; 

    for (i = Py_SIZE(o); --i >= 0;) 
     Py_VISIT(o->ob_item[i]); 
    return 0; 
} 

я вижу, это утверждение, что циклические ссылки обнаружены, кроме случаев, когда объектов задействованных метода __del__().

Вы правильно - детектор цикла Python может обнаружить и собрать циклы если они не содержат объекты с методом __del__, так как нет никакого способа для интерпретатора, чтобы безопасно удалить эти объекты (чтобы получить интуиции о том, почему это Представьте, что у вас есть два объекта с методами __del__, которые ссылаются друг на друга. В каком порядке они должны быть освобождены?).

Когда объекты с использованием метода __del__ задействованы в цикле, сборщик мусора будет вставлять их в отдельный список (доступный через gc.garbage), чтобы программист мог вручную «разобраться» с ними.

+1

В документах я увидел следующее заявление: «Детектор циклов способен обнаруживать циклы мусора и может вернуть их до тех пор, пока в методах Python (__del __() не будут реализованы финализаторы). Когда есть такие финализаторы, детектор выставляет циклы через модуль gc (в частности, переменную мусора в этом модуле). «http://docs.python.org/extending/extending.html#reference-counts .... Я интерпретировал это как означающее, что gc был отказоустойчивый/медленный метод. Был ли я неверно истолкован документами (я легко мог бы быть)? – user1245262

+2

@ user1245262, проблема '__del__' на самом деле не связана с поиском мусора. Python обнаруживает, что такие объекты являются мусором и вставляют их в список 'gc.garbage'. Единственная причина, по которой такие объекты не удаляются, заключается в том, что python не может определить, какой безопасный порядок их удалить. –

+1

А, простите, я забыл ответить на этот вопрос. Я считаю, что это означает: «когда нет объектов с методами' __del__', детектор цикла может восстановить все. Однако, поскольку детектор цикла не может безопасно собирать объекты с помощью методов '__del__', циклы, связанные с этими объектами, через модуль 'gc', позволяя программисту вручную очистить их». –

4

Как Python обнаруживает & бесплатные ссылки на циркулярную память перед использованием модуля gc?

сборщик мусора Python (а не на самом деле модуль gc, который является только интерфейс Python для сборки мусора) делает это. Таким образом, Python не обнаруживает и освобождает ссылки на циркулярную память, прежде чем использовать сборщик мусора.

Python обычно освобождает большинство объектов, как только их число ссылок достигает нуля. (Я говорю «больше всего», потому что он никогда не освобождает, например, небольшие целые числа или интернированные строки.) В случае циклических ссылок это никогда не происходит, поэтому сборщик мусора периодически ходит по памяти и освобождает объекты с циркулярной ссылкой.

Все это, конечно, зависит от CPython. Другие реализации Python имеют разное управление памятью (Jython = Java VM, IronPython = Microsoft .NET CLR).

+0

Не совсем точно. Python не перемещает память и освобождает недостижимые объекты. Он просматривает память и обнаруживает циклы ссылок и освобождает их. –

+0

Это «ходьба памяти»? Я думал, что это списки ссылок? (или «ходящая память» имеет техническое определение, с которым я не знаком?) –

+0

Модуль 'gc' * является * циклическим сборщиком мусора. Это не просто интерфейс Python, это реализация. –

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