Поддержка циклического сбора мусора
Поддержка Python для обнаружения и сбора мусора, связанного с циклическими ссылками, требует поддержки со стороны типов объектов, которые являются «контейнерами» для других объектов, также способных быть контейнерами. Типам, которые не хранят ссылки на другие объекты или хранят ссылки только на атомарные типы (например, числа или строки), не нужно явно поддерживать сборку мусора.
Чтобы создать тип-контейнер, поле tp_flags объекта типа должно включать Py_TPFLAGS_HAVE_GC, а также реализацию обработчика tp_traverse. Если экземпляры типа изменяемы, необходимо также предоставить реализацию tp_clear.
-
Py_TPFLAGS_HAVE_GC -
Объекты с типом, для которого установлен этот флаг, должны соответствовать описанным здесь правилам. Для удобства такие объекты будут называться объектами-контейнерами.
Конструкторы типов-контейнеров должны соответствовать двум правилам:
- Память для объекта должна выделяться с помощью
PyObject_GC_NewилиPyObject_GC_NewVar. - После инициализации всех полей, которые могут содержать ссылки на другие контейнеры, необходимо вызвать
PyObject_GC_Track().
Аналогично, деаллокатор объекта должен соответствовать двум похожим правилам:
- Перед тем как поля, ссылающиеся на другие контейнеры, станут недействительными, необходимо вызвать
PyObject_GC_UnTrack(). -
Память объекта должна освобождаться с помощью
PyObject_GC_Del().Предупреждение
Если тип добавляет Py_TPFLAGS_HAVE_GC, он обязан реализовать хотя бы обработчик
tp_traverseили явно использовать обработчик одного из своих суперклассов.При вызове
PyType_Ready()или некоторых API, которые косвенно вызывают его, напримерPyType_FromSpecWithBases()илиPyType_FromSpec(), интерпретатор автоматически заполнит поляtp_flags,tp_traverseиtp_clear, если тип наследуется от класса, реализующего протокол сборщика мусора, а дочерний класс не содержит флагPy_TPFLAGS_HAVE_GC.
-
PyObject_GC_New(TYPE, typeobj) -
Аналог
PyObject_New, предназначенный для объектов-контейнеров с установленным флагомPy_TPFLAGS_HAVE_GC.Не вызывайте эту макрокоманду напрямую для выделения памяти под объект; вместо этого вызовите слот
tp_allocтипа.При заполнении слота
tp_allocтипа предпочтительнее использоватьPyType_GenericAlloc(), а не пользовательскую функцию, которая просто вызывает эту макрокоманду.Память, выделенная этой макрокомандой, необходимо освободить с помощью
PyObject_GC_Del()(обычно это делается через слотtp_freeобъекта).
-
PyObject_GC_NewVar(TYPE, typeobj, size) -
Аналог
PyObject_NewVar, предназначенный для объектов-контейнеров с установленным флагомPy_TPFLAGS_HAVE_GC.Не вызывайте эту макрокоманду напрямую для выделения памяти под объект; вместо этого вызовите слот
tp_allocтипа.При заполнении слота
tp_allocтипа предпочтительнее использоватьPyType_GenericAlloc(), а не пользовательскую функцию, которая просто вызывает эту макрокоманду.Память, выделенная этой макрокомандой, необходимо освободить с помощью
PyObject_GC_Del()(обычно это делается через слотtp_freeобъекта).
-
PyObject *PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size) -
Это нестабильный API. Он может измениться без предупреждения в минорных выпусках.
Аналог
PyObject_GC_New, который выделяет в конце объекта (по смещениюtp_basicsize) дополнительно extra_size байт. Выделенная память инициализируется нулями, за исключениемPython object header.Дополнительные данные будут освобождены вместе с объектом, но в остальном Python ими не управляет.
Память, выделенную этой функцией, необходимо освободить с помощью
PyObject_GC_Del()(обычно это делается через слотtp_freeобъекта).Предупреждение
Функция помечена как нестабильная, поскольку окончательный механизм резервирования дополнительных данных после экземпляра ещё не определён. Для выделения переменного числа полей предпочтительнее использовать
PyVarObjectиtp_itemsize.Добавлено в версии 3.12.
-
PyObject_GC_Resize(TYPE, op, newsize) -
Изменяет размер объекта, выделенного с помощью
PyObject_NewVar. Возвращает объект изменённого размера типаTYPE*(обозначает любой тип C) илиNULLв случае ошибки.op должен иметь тип PyVarObject* и ещё не должен отслеживаться сборщиком. newsize должен иметь тип
Py_ssize_t.
-
void PyObject_GC_Track(PyObject *op) -
Входит в стабильный ABI.
Добавляет объект op в набор объектов-контейнеров, отслеживаемых сборщиком. Сборщик может запуститься в неожиданный момент, поэтому отслеживаемые объекты должны быть корректными. Эту функцию следует вызвать после того, как все поля, обрабатываемые обработчиком
tp_traverse, станут корректными; обычно это делается ближе к концу конструктора.
-
int PyObject_IS_GC(PyObject *obj) -
Возвращает ненулевое значение, если объект реализует протокол сборщика мусора, и 0 в противном случае.
Если эта функция возвращает 0, объект не может отслеживаться сборщиком мусора.
-
int PyObject_GC_IsTracked(PyObject *op) -
Входит в стабильный ABI начиная с версии 3.9.
Возвращает 1, если тип объекта op реализует протокол GC и op в данный момент отслеживается сборщиком мусора, и 0 в противном случае.
Эта функция аналогична функции Python
gc.is_tracked().Добавлено в версии 3.9.
-
int PyObject_GC_IsFinalized(PyObject *op) -
Входит в стабильный ABI начиная с версии 3.9.
Возвращает 1, если тип объекта op реализует протокол GC и сборщик мусора уже завершил обработку op, и 0 в противном случае.
Эта функция аналогична функции Python
gc.is_finalized().Добавлено в версии 3.9.
-
void PyObject_GC_Del(void *op) -
Входит в стабильный ABI.
Освобождает память, выделенную для объекта с помощью
PyObject_GC_NewилиPyObject_GC_NewVar.Не вызывайте эту функцию напрямую для освобождения памяти объекта; вместо этого вызовите слот
tp_freeтипа.Не используйте эту функцию для памяти, выделенной с помощью
PyObject_New,PyObject_NewVarили связанных функций выделения памяти; вместо этого используйтеPyObject_Free().См. также
-
PyObject_Free()— эквивалент этой функции для объектов, не отслеживаемых сборщиком мусора. PyObject_GC_NewPyObject_GC_NewVarPyType_GenericAlloc()tp_free
-
-
void PyObject_GC_UnTrack(void *op) -
Входит в стабильный ABI.
Удаляет объект op из набора объектов-контейнеров, отслеживаемых сборщиком. Обратите внимание: для повторного добавления объекта в набор отслеживаемых объектов можно снова вызвать
PyObject_GC_Track(). Деаллокатор (обработчикtp_dealloc) должен вызвать эту функцию для объекта до того, как какие-либо поля, используемые обработчикомtp_traverse, станут недействительными.
Изменено в версии 3.8: Макрокоманды _PyObject_GC_TRACK() и _PyObject_GC_UNTRACK() удалены из общедоступного C API.
Обработчик tp_traverse принимает параметр-функцию следующего типа:
-
typedef int (*visitproc)(PyObject *object, void *arg) -
Входит в стабильный ABI.
Тип функции-обходчика, передаваемой обработчику
tp_traverse. Функцию следует вызывать, передав объект для обхода в качестве object, а третий параметр обработчикаtp_traverse— в качестве arg. Ядро Python использует несколько функций-обходчиков для обнаружения циклического мусора; предполагается, что пользователям не потребуется писать собственные функции-обходчики.
Обработчик tp_traverse должен иметь следующий тип:
-
typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg) -
Входит в стабильный ABI.
Функция обхода объекта-контейнера. Реализация должна вызывать функцию visit для каждого объекта, непосредственно содержащегося в self; параметрами visit должны быть содержащийся объект и значение arg, переданное обработчику. Функцию visit нельзя вызывать с аргументом-объектом
NULL. Если visit возвращает ненулевое значение, его следует немедленно вернуть.Функция обхода не должна иметь побочных эффектов. Реализация не должна изменять счётчики ссылок каких-либо объектов Python, а также создавать или уничтожать объекты Python.
Чтобы упростить написание обработчиков tp_traverse, предусмотрена макрокоманда Py_VISIT(). Чтобы использовать эту макрокоманду, реализация tp_traverse должна называть свои аргументы строго visit и arg:
-
Py_VISIT(o) -
Если PyObject* o не является
NULL, вызывает обратный вызов visit с аргументами o и arg. Если visit возвращает ненулевое значение, возвращает его. С этой макрокомандой обработчикиtp_traverseвыглядят так:static int my_traverse(Noddy *self, visitproc visit, void *arg) { Py_VISIT(self->foo); Py_VISIT(self->bar); return 0; }
Обработчик tp_clear должен иметь тип inquiry или быть равен NULL, если объект неизменяем.
-
typedef int (*inquiry)(PyObject *self) -
Входит в стабильный ABI.
Удаляет ссылки, которые могли привести к циклам ссылок. Неизменяемым объектам не нужно определять этот метод, поскольку они никогда не могут напрямую создавать циклы ссылок. Обратите внимание: после вызова этого метода объект всё ещё должен оставаться корректным (не вызывайте просто
Py_DECREF()для ссылки). Сборщик вызовет этот метод, если обнаружит, что объект участвует в цикле ссылок.
Управление состоянием сборщика мусора
C API предоставляет следующие функции для управления запусками сборщика мусора.
-
Py_ssize_t PyGC_Collect(void) -
Входит в стабильный ABI.
Выполняет полную сборку мусора, если сборщик мусора включён. (Обратите внимание:
gc.collect()выполняет её безусловно.)Возвращает количество собранных объектов плюс количество недостижимых объектов, которые не удалось собрать. Если сборщик мусора отключён или уже выполняет сборку, немедленно возвращает
0. Ошибки во время сборки мусора передаются вsys.unraisablehook. Эта функция не вызывает исключений.
-
int PyGC_Enable(void) -
Входит в стабильный ABI начиная с версии 3.10.
Включает сборщик мусора: аналогично
gc.enable(). Возвращает предыдущее состояние: 0, если сборщик был отключён, и 1, если включён.Добавлено в версии 3.10.
-
int PyGC_Disable(void) -
Входит в стабильный ABI начиная с версии 3.10.
Отключает сборщик мусора: аналогично
gc.disable(). Возвращает предыдущее состояние: 0, если сборщик был отключён, и 1, если включён.Добавлено в версии 3.10.
-
int PyGC_IsEnabled(void) -
Входит в стабильный ABI начиная с версии 3.10.
Проверяет состояние сборщика мусора: аналогично
gc.isenabled(). Возвращает текущее состояние: 0, если сборщик отключён, и 1, если включён.Добавлено в версии 3.10.
Получение сведений о состоянии сборщика мусора
C API предоставляет следующий интерфейс для получения сведений о сборщике мусора.
-
void PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg) -
Это нестабильный API. Он может измениться без предупреждения в минорных выпусках.
Запускает предоставленный callback для всех живых объектов, поддерживающих GC. arg передаётся каждому вызову callback.
Предупреждение
Если обратный вызов выделяет или освобождает новые объекты, поведение не определено: неизвестно, будут ли эти объекты посещены.
Во время выполнения сборка мусора отключена. Явный запуск сборки в обратном вызове может привести к неопределённому поведению, например к многократному посещению одних и тех же объектов или к тому, что некоторые объекты не будут посещены вовсе.
Добавлено в версии 3.12.
-
typedef int (*gcvisitobjects_t)(PyObject *object, void *arg) -
Тип функции-обходчика, передаваемой в
PyUnstable_GC_VisitObjects(). arg совпадает с arg, переданным вPyUnstable_GC_VisitObjects. Возвратите1, чтобы продолжить итерацию, или0, чтобы остановить её. Другие возвращаемые значения пока зарезервированы, поэтому поведение при возврате любого другого значения не определено.Добавлено в версии 3.12.
© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/c-api/gcsupport.html