Spec-Zone.ru › Python 3.11

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

Обзор

Управление памятью в 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(), для выделения памяти для буферов.

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

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

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

Интерфейс «сырой» памяти

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

Распределяющий памяти использует следующие функции: 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.

PyMem_New(TYPE, n)

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

PyMem_Resize(p, TYPE, n)

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

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

void PyMem_Del(void *p)

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

Кроме того, для вызова аллокатора памяти Python непосредственно, без участия функций API C, перечисленных выше, предоставляются следующие наборы макросов. Однако обратите внимание, что их использование не сохраняет двоичную совместимость между версиями 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)

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

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

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

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

См. также PyPreConfig.allocator и Предварительная инициализация Python с PyPreConfig.

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

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

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

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

END_OF_DOCUMENT_MARKER

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

Когда Python построен в отладочном режиме, функция PyMem_SetupDebugHooks() вызывается на этапе предварительной инициализации Python (Предварительная инициализация 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 КБ на 32-битных платформах или 1 МБ на 64-битных платформах. Для выделения памяти больше 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)

выделение арены размером в bytes

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

освобождение арены

void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator)

Получение алгоритма выделения памяти в аренах.

void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator)

Установка алгоритма выделения памяти в аренах.

API C tracemalloc

Новое в версии 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.

Примеры

Вот пример из раздела Обзор, переписанный так, что буфер ввода-вывода выделяется из кучи 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.11/c-api/memory.html

Spec-Zone.ru

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