Spec-Zone.ru › Python 3.10

Управление памятью

Обзор

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

На самом низком уровне, непосредственный (сырой) выделение памяти гарантирует, что в частной куче достаточно места для хранения всех данных, связанных с Python, взаимодействуя с менеджером памяти операционной системы. Над непосредственным (сырым) выделением памяти работают несколько выделений памяти, специфичных для объектов, которые работают с одной и той же кучей и реализуют различные стратегии управления памятью, адаптированные к особенностям каждого типа объекта. Например, объекты целых чисел управляются в куче по-другому, чем строки, кортежи или словари, поскольку целые числа подразумевают различные требования к хранению и компромиссы между скоростью и объёмом памяти. Таким образом, менеджер памяти Python делегирует часть работы выделениям памяти, специфичным для объектов, но гарантирует, что последние работают в рамках частной кучи.

Важно понимать, что управление кучей Python выполняется самим интерпретатором, и пользователь не имеет к этому никакого доступа, даже если он регулярно манипулирует указателями объектов на блоки памяти внутри этой кучи. Выделение памяти кучи для объектов Python и других внутренних буферов выполняется по запросу менеджером памяти Python с помощью функций Python/C API, перечисленных в данном документе.

Чтобы избежать повреждения памяти, разработчики расширений никогда не должны пытаться работать с объектами Python с помощью функций, экспортированных библиотекой C: malloc(), calloc(), realloc() и free(). Это приведёт к смешанным вызовам между выделением памяти C и менеджером памяти Python с фатальными последствиями, потому что они реализуют разные алгоритмы и работают с разными кучами. Однако, можно безопасно выделять и освобождать блоки памяти с помощью выделения памяти C для отдельных целей, как показано в следующем примере:

PyObject *res;
char *buf = (char *) malloc(BUFSIZ); /* for I/O */

if (buf == NULL)
    return PyErr_NoMemory();
...Do some I/O operation involving buf...
res = PyBytes_FromString(buf);
free(buf); /* malloc'ed */
return res;

В этом примере запрос памяти для буфера ввода-вывода обрабатывается выделением памяти C. Менеджер памяти Python вовлечён только в выделение объекта байтов, возвращаемого в результате.

Однако в большинстве случаев рекомендуется выделять память из кучи Python, поскольку последняя находится под контролем менеджера памяти Python. Например, это требуется, когда интерпретатор расширяется новыми типами объектов, написанными на C. Другая причина использования кучи Python — необходимость информировать менеджер памяти Python о потребностях в памяти модуля расширения. Даже если запрашиваемая память используется исключительно для внутренних, узкоспециализированных целей, делегирование всех запросов памяти менеджеру памяти Python позволяет интерпретатору иметь более точное представление о своём общем объёме памяти. В результате, в определённых обстоятельствах, менеджер памяти Python может или не может инициировать соответствующие действия, такие как сборка мусора, уплотнение памяти или другие превентивные процедуры. Обратите внимание, что при использовании выделения памяти C, как показано в предыдущем примере, выделенная память для буфера ввода-вывода полностью выходит за пределы менеджера памяти Python.

См. также

Переменная окружения PYTHONMALLOC может использоваться для настройки используемых выделений памяти Python.

Переменная окружения PYTHONMALLOCSTATS может использоваться для вывода статистики выделения памяти выделения памяти pymalloc каждый раз при создании новой области выделения pymalloc и при завершении работы.

Области выделения

Все функции выделения принадлежат одной из трёх различных «областей» (см. также PyMemAllocatorDomain). Эти области представляют различные стратегии выделения и оптимизированы для различных целей. Конкретные подробности о том, как каждая область выделяет память или какие внутренние функции использует каждая область, считаются деталями реализации, но для отладки можно найти упрощенную таблицу по адресу здесь. Нет жёстких требований к использованию памяти, возвращаемой функциями выделения, относящимися к данной области, только для целей, намеченных этой областью (хотя это рекомендуемая практика). Например, можно использовать память, возвращаемую PyMem_RawMalloc() для выделения объектов Python или память, возвращаемую PyObject_Malloc() для выделения памяти для буферов.

Три области выделения:

  • Область непосредственного (сырого) выделения: предназначена для выделения памяти для буферов памяти общего назначения, где выделение должно происходить у выделения системы или где выделение может работать без блокировки интерпретатора. Память запрашивается непосредственно у системы.
  • Область «Mem»: предназначена для выделения памяти для буферов Python и буферов памяти общего назначения, где выделение должно выполняться при удержании блокировки интерпретатора. Память берётся из частной кучи Python.
  • Область объектов: предназначена для выделения памяти, принадлежащей объектам Python. Память берётся из частной кучи Python.

При освобождении памяти, ранее выделенной функциями выделения, относящимися к данной области, должны использоваться соответствующие функции освобождения. Например, PyMem_Free() необходимо использовать для освобождения памяти, выделенной с помощью PyMem_Malloc().

Интерфейс непосредственного (сырого) выделения памяти

Следующие наборы функций являются оболочками для выделения памяти системы. Эти функции потокобезопасны, не требуется удерживать блокировку интерпретатора.

В стандартном выделении сырой памяти используются следующие функции: malloc(), calloc(), realloc() и free(); вызов malloc(1) (или calloc(1, 1)) при запросе нулевого количества байтов.

Новое в версии 3.4.

void *PyMem_RawMalloc(size_t n)

Выделяет n байтов и возвращает указатель типа void* на выделенную память или NULL, если запрос не удался.

Запрос нулевого количества байтов возвращает отдельный не-NULL указатель, если это возможно, как если бы был вызван PyMem_RawMalloc(1). Память не будет инициализирована каким-либо образом.

void *PyMem_RawCalloc(size_t nelem, size_t elsize)

Выделяет nelem элементов, каждый размером elsize байт, и возвращает указатель типа void* на выделенную память или NULL, если запрос не удался. Память инициализируется нулями.

Запрос нуля элементов или элементов нулевого размера возвращает отдельный не-NULL указатель, если это возможно, как если бы был вызван PyMem_RawCalloc(1, 1).

Новое в версии 3.5.

void *PyMem_RawRealloc(void *p, size_t n)

Изменяет размер блока памяти, на который указывает p, на n байт. Содержимое будет неизменным до минимального из старого и нового размеров.

Если p — NULL, вызов эквивалентен PyMem_RawMalloc(n); иначе, если n равно нулю, блок памяти изменяется по размеру, но не освобождается, и возвращаемый указатель не-NULL.

За исключением случая, когда p — NULL, он должен быть возвращён предыдущим вызовом PyMem_RawMalloc(), PyMem_RawRealloc() или PyMem_RawCalloc().

Если запрос не удался, PyMem_RawRealloc() возвращает NULL и p остаётся допустимым указателем на предыдущую область памяти.

void PyMem_RawFree(void *p)

Освобождает блок памяти, на который указывает p, который должен был быть возвращён предыдущим вызовом PyMem_RawMalloc(), PyMem_RawRealloc() или PyMem_RawCalloc(). В противном случае или если PyMem_RawFree(p) был вызван ранее, возникает неопределённое поведение.

Если p — NULL, никакая операция не выполняется.

END_OF_DOCUMENT_MARKER

Интерфейс памяти

Следующие функции, смоделированные по стандарту ANSI C, но определяющие поведение при запросе нулевого количества байтов, доступны для выделения и освобождения памяти из кучи Python.

В по умолчанию выделение памяти используется аллокатор памяти pymalloc.

Предупреждение

При использовании этих функций должен быть захвачен GIL.

Изменено в версии 3.6: По умолчанию используется аллокатор pymalloc вместо системного malloc().

void *PyMem_Malloc(size_t n)
Часть Стабильной ABI.

Выделяет n байтов и возвращает указатель типа void* на выделенную память или NULL, если запрос не удался.

Запрос нулевого количества байтов возвращает отдельный не-NULL указатель, если это возможно, как если бы была вызвана функция PyMem_Malloc(1). Память не будет инициализирована ни одним способом.

void *PyMem_Calloc(size_t nelem, size_t elsize)
Часть Стабильной ABI с версии 3.7.

Выделяет nelem элементов, размер каждого из которых в байтах равен elsize, и возвращает указатель типа void* на выделенную память или NULL, если запрос не удался. Память инициализируется нулями.

Запрос нулевого количества элементов или элементов размером в ноль байтов возвращает отдельный не-NULL указатель, если это возможно, как если бы была вызвана функция PyMem_Calloc(1, 1).

Введено в версии 3.5.

void *PyMem_Realloc(void *p, size_t n)
Часть Стабильной ABI.

Изменяет размер блока памяти, на который указывает p, на n байтов. Содержимое сохранится до минимального значения из старого и нового размеров.

Если p равен NULL, вызов эквивалентен PyMem_Malloc(n); в противном случае, если n равно нулю, блок памяти изменяется в размере, но не освобождается, и возвращаемый указатель не является NULL.

Если p не равен NULL, он должен был быть возвращён предыдущим вызовом PyMem_Malloc(), PyMem_Realloc() или PyMem_Calloc().

Если запрос не удался, PyMem_Realloc() возвращает NULL, а p остаётся допустимым указателем на предыдущий блок памяти.

void PyMem_Free(void *p)
Часть Стабильной ABI.

Освобождает блок памяти, на который указывает p, который должен был быть возвращён предыдущим вызовом PyMem_Malloc(), PyMem_Realloc() или PyMem_Calloc(). В противном случае, или если PyMem_Free(p) было вызвано ранее, происходит неопределённое поведение.

Если p равно NULL, никакой операции не выполняется.

Для удобства предоставлены следующие макросы, ориентированные на типы. Обратите внимание, что TYPE относится к любому типу C.

TYPE *PyMem_New(TYPE, size_t n)

То же, что и PyMem_Malloc(), но выделяет (n * sizeof(TYPE)) байтов памяти. Возвращает указатель, преобразованный к типу TYPE*. Память не будет инициализирована ни одним способом.

TYPE *PyMem_Resize(void *p, TYPE, size_t n)

То же, что и PyMem_Realloc(), но размер блока памяти изменяется на (n * sizeof(TYPE)) байтов. Возвращает указатель, преобразованный к типу TYPE*. При возвращении p будет указателем на новый блок памяти или NULL в случае неудачи.

Это макрос препроцессора C; p всегда переназначается. Сохраните исходное значение p, чтобы избежать потери памяти при обработке ошибок.

void PyMem_Del(void *p)

То же, что и PyMem_Free().

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

  • PyMem_MALLOC(size)
  • PyMem_NEW(type, size)
  • PyMem_REALLOC(ptr, size)
  • PyMem_RESIZE(ptr, type, size)
  • PyMem_FREE(ptr)
  • PyMem_DEL(ptr)

Аллокаторы объектов

Следующие наборы функций, смоделированные по стандарту ANSI C, но определяющие поведение при запросе нулевого количества байтов, доступны для выделения и освобождения памяти из кучи Python.

Примечание

Нет гарантии, что память, возвращённая этими аллокаторами, может быть успешно преобразована в объект Python при перехвате функций выделения в этом домене методами, описанными в разделе Настройка аллокаторов памяти.

В по умолчанию выделение памяти объектов используется аллокатор памяти pymalloc.

Предупреждение

При использовании этих функций должен быть захвачен GIL.

void *PyObject_Malloc(size_t n)
Часть Стабильной ABI.

Выделяет n байтов и возвращает указатель типа void* на выделенную память или NULL, если запрос не удался.

Запрос нулевого количества байтов возвращает отдельный не-NULL указатель, если это возможно, как если бы была вызвана функция PyObject_Malloc(1). Память не будет инициализирована ни одним способом.

void *PyObject_Calloc(size_t nelem, size_t elsize)
Часть Стабильной ABI с версии 3.7.

Выделяет nelem элементов, размер каждого из которых в байтах равен elsize, и возвращает указатель типа void* на выделенную память или NULL, если запрос не удался. Память инициализируется нулями.

Запрос нулевого количества элементов или элементов размером в ноль байтов возвращает отдельный не-NULL указатель, если это возможно, как если бы была вызвана функция PyObject_Calloc(1, 1).

Введено в версии 3.5.

void *PyObject_Realloc(void *p, size_t n)
Часть Стабильной ABI.

Изменяет размер блока памяти, на который указывает p, на n байтов. Содержимое сохранится до минимального значения из старого и нового размеров.

Если p равен NULL, вызов эквивалентен PyObject_Malloc(n); в противном случае, если n равно нулю, блок памяти изменяется в размере, но не освобождается, и возвращаемый указатель не является NULL.

Если p не равен NULL, он должен был быть возвращён предыдущим вызовом PyObject_Malloc(), PyObject_Realloc() или PyObject_Calloc().

Если запрос не удался, PyObject_Realloc() возвращает NULL, а p остаётся допустимым указателем на предыдущий блок памяти.

void PyObject_Free(void *p)
Часть Стабильной ABI.

Освобождает блок памяти, на который указывает p, который должен был быть возвращён предыдущим вызовом PyObject_Malloc(), PyObject_Realloc() или PyObject_Calloc(). В противном случае, или если PyObject_Free(p) было вызвано ранее, происходит неопределённое поведение.

Если p равно NULL, никакой операции не выполняется.

END_OF_DOCUMENT_MARKER

Стандартные распределения памяти

Стандартные распределения памяти:

Конфигурация

Имя

PyMem_RawMalloc

PyMem_Malloc

PyObject_Malloc

Релизная сборка

"pymalloc"

malloc

pymalloc

pymalloc

Отладочная сборка

"pymalloc_debug"

malloc + отладка

pymalloc + отладка

pymalloc + отладка

Релизная сборка без pymalloc

"malloc"

malloc

malloc

malloc

Отладочная сборка без pymalloc

"malloc_debug"

malloc + отладка

malloc + отладка

malloc + отладка

Легенда:

  • Имя: значение для переменной окружения PYTHONMALLOC.
  • malloc: системные распределятели из стандартной библиотеки C, функции C: malloc(), calloc(), realloc() и free().
  • pymalloc: распределитель памяти pymalloc.
  • «+ отладка»: с активацией отладочных хуков в распределятелях памяти Python.
  • «Отладочная сборка»: сборка Python в режиме отладки.

Настройка распределятелей памяти

Новое в версии 3.4.

type PyMemAllocatorEx

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

Поле

Значение

void *ctx

контекст пользователя, передаваемый в качестве первого аргумента

void* malloc(void *ctx, size_t size)

выделение блока памяти

void* calloc(void *ctx, size_t nelem, size_t elsize)

выделение блока памяти, инициализированного нулями

void* realloc(void *ctx, void *ptr, size_t new_size)

выделение или изменение размера блока памяти

void free(void *ctx, void *ptr)

освобождение блока памяти

Изменено в версии 3.5: Структура PyMemAllocator была переименована в PyMemAllocatorEx, и было добавлено новое поле calloc.

type PyMemAllocatorDomain

Перечисление, используемое для идентификации области распределения. Области:

PYMEM_DOMAIN_RAW

Функции:

  • PyMem_RawMalloc()
  • PyMem_RawRealloc()
  • PyMem_RawCalloc()
  • PyMem_RawFree()
PYMEM_DOMAIN_MEM

Функции:

  • PyMem_Malloc(),
  • PyMem_Realloc()
  • PyMem_Calloc()
  • PyMem_Free()
PYMEM_DOMAIN_OBJ

Функции:

  • PyObject_Malloc()
  • PyObject_Realloc()
  • PyObject_Calloc()
  • PyObject_Free()
void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)

Получить распределятель блоков памяти указанной области.

void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)

Установить распределятель блоков памяти указанной области.

Новый распределятель должен возвращать другой указатель, не равный NULL, при запросе нулевого количества байт.

Для области PYMEM_DOMAIN_RAW, распределятель должен быть потокобезопасным: блокировка глобального интерпретатора (GIL) не должна быть взята при вызове распределятеля.

Если новый распределятель не является хуком (не вызывает предыдущий распределятель), необходимо вызвать функцию PyMem_SetupDebugHooks() для повторной установки отладочных хуков поверх нового распределятеля.

Предупреждение

PyMem_SetAllocator() имеет следующий контракт:

  • Его можно вызывать после Py_PreInitialize() и перед Py_InitializeFromConfig() для установки пользовательского распределятеля памяти. Нет ограничений на установленный распределятель, кроме тех, что накладываются областью (например, область Raw позволяет вызывать распределятель без блокировки GIL). Подробнее см. раздел об областях распределятелей.
  • Если вызывается после завершения инициализации Python (после вызова Py_InitializeFromConfig()), распределятель должен обернуть существующий распределятель. Замена текущего распределятеля другим произвольным не поддерживается.
void PyMem_SetupDebugHooks(void)

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

END_OF_DOCUMENT_MARKER

Отладочные хуки в менеджерах памяти Python

Когда Python скомпилирован в отладочном режиме, функция PyMem_SetupDebugHooks() вызывается на этапе предварительной инициализации Python для установки отладочных хуков в менеджерах памяти Python, чтобы обнаруживать ошибки памяти.

Переменная окружения PYTHONMALLOC может использоваться для установки отладочных хуков в Python, скомпилированном в режиме релиз (например: PYTHONMALLOC=debug).

Функция PyMem_SetupDebugHooks() может использоваться для установки отладочных хуков после вызова PyMem_SetAllocator().

Эти отладочные хуки заполняют динамически выделенные блоки памяти специальными, распознаваемыми битовыми шаблонами. Новая выделенная память заполняется байтом 0xCD (PYMEM_CLEANBYTE), освобожденная память заполняется байтом 0xDD (PYMEM_DEADBYTE). Блоки памяти окружены «запрещёнными байтами», заполненными байтом 0xFD (PYMEM_FORBIDDENBYTE). Последовательности этих байтов вряд ли будут являться валидными адресами, числами с плавающей запятой или ASCII-строками.

Проверка во время выполнения:

  • Обнаружение нарушений API. Например, обнаружение вызова PyObject_Free() для блока памяти, выделенного с помощью PyMem_Malloc().
  • Обнаружение записи перед началом буфера (ошибка подтекания буфера).
  • Обнаружение записи после конца буфера (переполнение буфера).
  • Проверка того, что GIL захвачен при вызове функций выделения памяти для областей PYMEM_DOMAIN_OBJ (например, PyObject_Malloc()) и PYMEM_DOMAIN_MEM (например, PyMem_Malloc()).

При ошибке отладочные хуки используют модуль tracemalloc для получения стека вызовов, где был выделен блок памяти. Стек вызовов отображается только в том случае, если tracemalloc отслеживает выделения памяти Python, и блок памяти был отслежен.

Пусть S = sizeof(size_t). 2*S байта добавляются к каждому концу каждого блока из N байт, запрошенных для выделения. Структура памяти выглядит следующим образом, где p представляет адрес, возвращаемый функцией типа malloc или realloc (p[i:j] обозначает срез байтов от *(p+i) включительно до *(p+j) не включительно; обратите внимание, что обработка отрицательных индексов отличается от обработки срезов в Python):

p[-2*S:-S]

Количество байтов, первоначально запрошенных для выделения. Это значение типа size_t, в формате big-endian (для удобства чтения в дампе памяти).

p[-S]

Идентификатор API (ASCII-символ):

  • 'r' для PYMEM_DOMAIN_RAW.
  • 'm' для PYMEM_DOMAIN_MEM.
  • 'o' для PYMEM_DOMAIN_OBJ.
p[-S+1:0]

Копии PYMEM_FORBIDDENBYTE. Используются для отслеживания попыток записи/чтения за пределы буфера.

p[0:N]

Запрошенная память, заполненная копиями PYMEM_CLEANBYTE. Используется для обнаружения ссылок на неинициализированную память. При вызове функции realloc, запрашивающей больший блок памяти, новые дополнительные байты также заполняются PYMEM_CLEANBYTE. При вызове функции free эти байты перезаписываются PYMEM_DEADBYTE для обнаружения ссылок на освобождённую память. При вызове функции realloc, запрашивающей меньший блок памяти, избыточные старые байты также заполняются PYMEM_DEADBYTE.

p[N:N+S]

Копии PYMEM_FORBIDDENBYTE. Используются для отслеживания попыток записи/чтения за пределы буфера.

p[N+S:N+2*S]

Используется только если определена макрос PYMEM_DEBUG_SERIALNO (по умолчанию не определён).

Порядковый номер, увеличивающийся на 1 при каждом вызове функций типа malloc или realloc. Представлен в формате big-endian size_t. Если позже обнаружена «плохая память», порядковый номер предоставляет отличный способ установить точку останова при следующем запуске, чтобы зафиксировать момент, когда этот блок был выдан. Статическая функция bumpserialno() в obmalloc.c — единственное место, где увеличивается порядковый номер, что позволяет легко установить точку останова.

Функции realloc и free сначала проверяют, что байты PYMEM_FORBIDDENBYTE по обеим сторонам блока не изменены. Если они были изменены, диагностическое сообщение выводится в stderr, и программа прерывается с помощью Py_FatalError(). Другой основной режим отказа — вызвать ошибку памяти, когда программа считывает один из специальных шаблонов и пытается использовать его как адрес. Если вы попали в отладчик в этот момент и посмотрели на объект, вы, вероятно, увидите, что он полностью заполнен PYMEM_DEADBYTE (означает, что освобождённая память используется) или PYMEM_CLEANBYTE (означает, что используется неинициализированная память).

Изменено в версии 3.6: Функция PyMem_SetupDebugHooks() теперь также работает с Python, скомпилированным в режиме релиз. При ошибке отладочные хуки теперь используют tracemalloc для получения стека вызовов, где был выделен блок памяти. Отладочные хуки теперь также проверяют, что GIL захвачен при вызове функций из областей PYMEM_DOMAIN_OBJ и PYMEM_DOMAIN_MEM.

Изменено в версии 3.8: Шаблоны байтов 0xCB (PYMEM_CLEANBYTE), 0xDB (PYMEM_DEADBYTE) и 0xFB (PYMEM_FORBIDDENBYTE) были заменены на 0xCD, 0xDD и 0xFD для использования тех же значений, что и у отладочных хуков Windows CRT malloc() и free().

Менеджер памяти pymalloc

Python имеет менеджер памяти pymalloc, оптимизированный для небольших объектов (не больше 512 байт) с коротким сроком жизни. Он использует карты памяти, называемые «аренами», с фиксированным размером 256 КБ. Для выделения памяти больше 512 байт используется обращение к PyMem_RawMalloc() и PyMem_RawRealloc().

pymalloc является по умолчанию менеджером памяти для областей PYMEM_DOMAIN_MEM (например, PyMem_Malloc()) и PYMEM_DOMAIN_OBJ (например, PyObject_Malloc()).

Менеджер ареной использует следующие функции:

  • VirtualAlloc() и VirtualFree() на Windows,
  • mmap() и munmap() если доступны,
  • malloc() и free() в противном случае.

Этот менеджер выключен, если Python сконфигурирован с опцией --without-pymalloc. Он также может быть отключен во время выполнения с помощью переменной окружения PYTHONMALLOC (например: PYTHONMALLOC=malloc).

Настройка менеджера памяти pymalloc Arena

Введено в версии 3.4.

type PyObjectArenaAllocator

Структура, используемая для описания менеджера памяти ареной. Структура имеет три поля:

Поле

Значение

void *ctx

контекст пользователя, передаваемый как первый аргумент

void* alloc(void *ctx, size_t size)

выделить арену размером в байтах

void free(void *ctx, void *ptr, size_t size)

освободить арену

void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator)

Получить менеджер памяти ареной.

void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator)

Установить менеджер памяти ареной.

API tracemalloc для C

Введено в версии 3.7.

int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size)

Отследить блок выделенной памяти в модуле tracemalloc.

Возвращает 0 при успехе, -1 при ошибке (не удалось выделить память для хранения трассировки). Возвращает -2 если tracemalloc отключён.

Если блок памяти уже отслеживается, обновить существующую трассировку.

int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)

Прекратить отслеживание блока выделенной памяти в модуле tracemalloc. Ничего не делает, если блок не отслеживался.

Возвращает -2 если tracemalloc отключен, в противном случае возвращает 0.

END_OF_DOCUMENT_MARKER

Примеры

Вот пример из раздела Обзор, переписанный так, чтобы буфер ввода-вывода выделялся из кучи Python с использованием первого набора функций:

PyObject *res;
char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */

if (buf == NULL)
    return PyErr_NoMemory();
/* ...Do some I/O operation involving buf... */
res = PyBytes_FromString(buf);
PyMem_Free(buf); /* allocated with PyMem_Malloc */
return res;

Тот же код, использующий набор функций, ориентированный на тип:

PyObject *res;
char *buf = PyMem_New(char, BUFSIZ); /* for I/O */

if (buf == NULL)
    return PyErr_NoMemory();
/* ...Do some I/O operation involving buf... */
res = PyBytes_FromString(buf);
PyMem_Del(buf); /* allocated with PyMem_New */
return res;

Обратите внимание, что в двух примерах выше буфер всегда обрабатывается с помощью функций, принадлежащих одному набору. Действительно, необходимо использовать одну и ту же семейство API памяти для данного блока памяти, чтобы свести к минимуму риск смешения различных выделенщиков. Следующая последовательность кода содержит две ошибки, одна из которых помечена как критическая, так как она смешивает два разных выделенщика, работающих с разными кучами.

char *buf1 = PyMem_New(char, BUFSIZ);
char *buf2 = (char *) malloc(BUFSIZ);
char *buf3 = (char *) PyMem_Malloc(BUFSIZ);
...
PyMem_Del(buf3);  /* Wrong -- should be PyMem_Free() */
free(buf2);       /* Right -- allocated via malloc() */
free(buf1);       /* Fatal -- should be PyMem_Del()  */

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

Они будут объяснены в следующей главе о определении и реализации новых типов объектов на языке C.

© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/c-api/memory.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API