gcsupport.md
1> **Источник:** https://python-all.ru/2.6/c-api/gcsupport.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Поддержка циклической сборки мусора89Поддержка Python обнаружения и сбора мусора, связанного с циклическими ссылками, требует поддержки со стороны объектных типов, которые являются «контейнерами» для других объектов, которые также могут быть контейнерами. Типы, которые не хранят ссылок на другие объекты или хранят только ссылки на атомарные типы (например, числа или строки), не нуждаются в явной поддержке сборки мусора.1011Чтобы создать контейнерный тип, поле [`tp_flags`](https://python-all.ru/2.6/c-api/typeobj.html#tp_flags) объекта типа должно содержать флаг [`Py_TPFLAGS_HAVE_GC`](https://python-all.ru/2.6/c-api/typeobj.html#Py_TPFLAGS_HAVE_GC), а также нужно предоставить реализацию обработчика [`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse). Если экземпляры типа изменяемы, необходимо также реализовать [`tp_clear`](https://python-all.ru/2.6/c-api/typeobj.html#tp_clear).1213#### `Py_TPFLAGS_HAVE_GC`1415Объекты с типом, у которого установлен этот флаг, должны соответствовать правилам, описанным здесь. Для удобства такие объекты будут называться контейнерными объектами.1617Конструкторы контейнерных типов должны соответствовать двум правилам:18191. Память для объекта должна выделяться с помощью [`PyObject_GC_New()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_New) или [`PyObject_GC_NewVar()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_NewVar).202. Как только все поля, которые могут содержать ссылки на другие контейнеры, будут инициализированы, необходимо вызвать [`PyObject_GC_Track()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_Track).2122**TYPE\* `PyObject_GC_New`(TYPE, [PyTypeObject](https://python-all.ru/2.6/c-api/type.html#PyTypeObject) *\*type*)**2324Аналог2526[`PyObject_New()`](https://python-all.ru/2.6/c-api/allocation.html#PyObject_New)2728, но для контейнерных объектов с установленным флагом2930[`Py_TPFLAGS_HAVE_GC`](https://python-all.ru/2.6/c-api/typeobj.html#Py_TPFLAGS_HAVE_GC)3132.3334**TYPE\* `PyObject_GC_NewVar`(TYPE, [PyTypeObject](https://python-all.ru/2.6/c-api/type.html#PyTypeObject) *\*type*, Py\_ssize\_t *size*)**3536Аналог [`PyObject_NewVar()`](https://python-all.ru/2.6/c-api/allocation.html#PyObject_NewVar), но для контейнерных объектов с установленным флагом [`Py_TPFLAGS_HAVE_GC`](https://python-all.ru/2.6/c-api/typeobj.html#Py_TPFLAGS_HAVE_GC).3738Изменено в версии 2.5: Эта функция использовала тип `int` для *size*. Это может потребовать изменений в коде для корректной поддержки 64-битных систем.3940**TYPE\* `PyObject_GC_Resize`(TYPE, [PyVarObject](https://python-all.ru/2.6/c-api/structures.html#PyVarObject) *\*op*, Py\_ssize\_t *newsize*)**4142Изменяет размер объекта, выделенного функцией [`PyObject_NewVar()`](https://python-all.ru/2.6/c-api/allocation.html#PyObject_NewVar). Возвращает объект нового размера или *NULL* в случае ошибки.4344Изменено в версии 2.5: Эта функция использовала тип `int` для *newsize*. Это может потребовать изменений в коде для корректной поддержки 64-битных систем.4546**void `PyObject_GC_Track`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*op*)**4748Добавляет объект4950*op*5152в набор контейнерных объектов, отслеживаемых сборщиком. Сборщик может запускаться в неожиданные моменты, поэтому отслеживаемые объекты должны быть корректными. Этот вызов следует делать после того, как все поля, обрабатываемые обработчиком5354[`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse)5556, станут корректными, обычно ближе к концу конструктора.5758**void `_PyObject_GC_TRACK`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*op*)**5960Макроверсия6162[`PyObject_GC_Track()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_Track)6364. Не предназначена для использования в модулях расширения.6566Аналогично, деаллокатор объекта должен соответствовать такой же паре правил:67681. Перед тем как поля, ссылающиеся на другие контейнеры, станут недействительными, необходимо вызвать [`PyObject_GC_UnTrack()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_UnTrack).692. Память объекта должна освобождаться с помощью [`PyObject_GC_Del()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_Del).7071**void `PyObject_GC_Del`(void *\*op*)**7273Освобождает память, выделенную для объекта с помощью7475[`PyObject_GC_New()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_New)7677или7879[`PyObject_GC_NewVar()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_NewVar)8081.8283**void `PyObject_GC_UnTrack`(void *\*op*)**8485Удаляет объект8687*op*8889из набора контейнерных объектов, отслеживаемых сборщиком. Обратите внимание, что9091[`PyObject_GC_Track()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_Track)9293может быть вызвана снова для этого объекта, чтобы вернуть его в набор отслеживаемых. Деаллокатор (обработчик9495[`tp_dealloc`](https://python-all.ru/2.6/c-api/typeobj.html#tp_dealloc)9697) должен вызывать эту функцию для объекта до того, как какие-либо поля, используемые обработчиком9899[`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse)100101, станут недействительными.102103**void `_PyObject_GC_UNTRACK`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*op*)**104105Макроверсия106107[`PyObject_GC_UnTrack()`](https://python-all.ru/2.6/c-api/gcsupport.html#PyObject_GC_UnTrack)108109. Не предназначена для использования в модулях расширения.110111Обработчик [`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse) принимает параметр-функцию следующего типа:112113**int `(*visitproc)`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*object*, void *\*arg*)**114115Тип функции посещения, передаваемой обработчику116117[`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse)118119. Функцию следует вызывать с объектом для обхода в качестве120121*object*122123и третьим параметром обработчика124125[`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse)126127в качестве128129*arg*130131. Ядро Python использует несколько функций посещения для обнаружения циклического мусора; не предполагается, что пользователям понадобится писать собственные функции посещения.132133Обработчик [`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse) должен иметь следующий тип:134135**int `(*traverseproc)`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*self*, [visitproc](https://python-all.ru/2.6/c-api/gcsupport.html#visitproc) *visit*, void *\*arg*)**136137Функция обхода для контейнерного объекта. Реализации должны вызывать функцию138139*visit*140141для каждого объекта, непосредственно содержащегося в142143*self*144145, с параметрами146147*visit*148149: содержащийся объект и значение150151*arg*152153, переданное обработчику. Функция154155*visit*156157не должна вызываться с аргументом-объектом158159*NULL*160161. Если162163*visit*164165возвращает ненулевое значение, его следует немедленно вернуть.166167Для упрощения написания обработчиков [`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse) предоставляется макрос [`Py_VISIT()`](https://python-all.ru/2.6/c-api/gcsupport.html#Py_VISIT). Чтобы использовать этот макрос, реализация [`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse) должна называть свои аргументы именно *visit* и *arg*:168169**void `Py_VISIT`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*o*)**170171Вызывает колбэк *visit* с аргументами *o* и *arg*. Если *visit* возвращает ненулевое значение, возвращает его. С использованием этого макроса обработчики [`tp_traverse`](https://python-all.ru/2.6/c-api/typeobj.html#tp_traverse) выглядят так:172173```c174static int175my_traverse(Noddy *self, visitproc visit, void *arg)176{177 Py_VISIT(self->foo);178 Py_VISIT(self->bar);179 return 0;180}181```182183Новое в версии 2.4.184185Обработчик [`tp_clear`](https://python-all.ru/2.6/c-api/typeobj.html#tp_clear) должен иметь тип [`inquiry`](https://python-all.ru/2.6/c-api/gcsupport.html#inquiry) или *NULL*, если объект неизменяем.186187**int `(*inquiry)`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*self*)**188189Удаляет ссылки, которые могли создать циклические ссылки. Неизменяемые объекты могут не определять этот метод, так как они никогда не могут напрямую создавать циклические ссылки. Обратите внимание, что объект после вызова этого метода всё ещё должен быть корректным (нельзя просто вызвать190191[`Py_DECREF()`](https://python-all.ru/2.6/c-api/refcounting.html#Py_DECREF)192193на ссылку). Сборщик вызовет этот метод, если обнаружит, что этот объект вовлечён в циклическую ссылку.194