Управление памятью
Обзор
Управление памятью в 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при неудаче запроса.Запрос нулевых байтов возвращает отдельный ненулевой указатель, если это возможно, как если бы был вызван
PyMem_RawMalloc(1). Память не будет инициализирована каким-либо образом.
-
void *PyMem_RawCalloc(size_t nelem, size_t elsize) -
Выделяет nelem элементов, каждый размером в elsize байтов и возвращает указатель типа void* на выделенную память, или
NULLпри неудаче запроса. Память инициализируется нулями.Запрос нулевых элементов или элементов нулевого размера возвращает отдельный ненулевой указатель, если это возможно, как если бы был вызван
PyMem_RawCalloc(1, 1).Добавлен в версии 3.5.
-
void *PyMem_RawRealloc(void *p, size_t n) -
Изменяет размер блока памяти, на который указывает p, на n байтов. Содержимое будет неизменным до минимального из старого и нового размеров.
Если p равно
NULL, вызов эквивалентенPyMem_RawMalloc(n); в противном случае, если n равно нулю, блок памяти изменяет размер, но не освобождается, и возвращаемый указатель ненулевой.За исключением случая, когда 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, никакая операция не выполняется.
Интерфейс памяти
Следующие функции, моделированные по стандарту 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 напрямую, без привлечения функций 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, никакой операции не выполняется.
Установленные по умолчанию менеджеры памяти
Установленные по умолчанию менеджеры памяти:
Конфигурация | Имя | PyMem_RawMalloc | PyMem_Malloc | PyObject_Malloc |
|---|---|---|---|---|
Релизная сборка |
|
|
|
|
Отладочная сборка |
|
|
|
|
Релизная сборка без pymalloc |
|
|
|
|
Отладочная сборка без pymalloc |
|
|
|
|
Легенда:
- Имя: значение для переменной среды
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_DOMAIN_MEM -
Функции:
-
PYMEM_DOMAIN_OBJ -
Функции:
-
-
void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator) -
Получить менеджер блоков памяти заданной области.
-
void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator) -
Установить менеджер блоков памяти заданной области.
Новый менеджер должен возвращать указатель, отличный от
NULL, при запросе нулевого количества байтов.Для области
PYMEM_DOMAIN_RAW, менеджер должен быть потокобезопасным: блокировка глобального интерпретатора (GIL) не должна удерживаться при вызове менеджера.Для остальных областей менеджер также должен быть потокобезопасным: менеджер может вызываться в разных интерпретаторах, которые не используют общую
GIL.Если новый менеджер не является хуком (не вызывает предыдущий менеджер), необходимо вызвать функцию
PyMem_SetupDebugHooks()для повторной установки отладочных хуков поверх нового менеджера.См. также
PyPreConfig.allocatorи Предварительная инициализация Python с помощью PyPreConfig.Предупреждение
PyMem_SetAllocator()имеет следующий договор:- Его можно вызывать после
Py_PreInitialize()и передPy_InitializeFromConfig()для установки пользовательского менеджера памяти. На установленный менеджер нет ограничений, кроме тех, что накладываются областью (например, область Raw позволяет вызывать менеджер без удерживания GIL). Подробнее об областях менеджеров см. раздел об областях менеджеров. - Если вызов осуществляется после завершения инициализации Python (после вызова
Py_InitializeFromConfig()), менеджер должен оборачивать существующий менеджер. Замена текущего менеджера на произвольный не поддерживается.
Изменено в версии 3.12: Все менеджеры должны быть потокобезопасными.
- Его можно вызывать после
-
void PyMem_SetupDebugHooks(void) -
Настроить отладочные хуки в менеджерах памяти Python для обнаружения ошибок памяти.
Отладочные хуки для выделения памяти 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. При вызове функции освобождения, эти байты перезаписываются с помощью 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, чтобы использовать те же значения, что и отладочные хуки CRT Windows 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/c-api/memory.html