# メモリ管理

## 概要

Python におけるメモリ管理には、全ての Python オブジェクトとデータ構造が入ったプライベートヒープ (private heap) が必須です。プライベートヒープの管理は、内部的には Python メモリマネージャ (Python memory manager) が確実に行います。Python メモリマネージャには、共有 (sharing)、セグメント分割 (segmentation)、事前割り当て (preallocation)、キャッシュ化 (caching) といった、様々な動的記憶管理の側面を扱うために、個別のコンポーネントがあります。

最低水準層では、素のメモリ操作関数 (raw memory allocator) がオペレーティングシステムのメモリ管理機構とやりとりして、プライベートヒープ内にPython 関連の全てのデータを記憶するのに十分な空きがあるかどうか確認します。素のメモリ操作関数の上には、いくつかのオブジェクト固有のメモリ操作関数があります。これらは同じヒープを操作し、各オブジェクト型固有の事情に合ったメモリ管理ポリシを実装しています。例えば、整数オブジェクトは文字列やタプル、辞書とは違ったやり方でヒープ内で管理されます。というのも、整数には値を記憶する上で特別な要件があり、速度/容量のトレードオフが存在するからです。このように、Python メモリマネジャは作業のいくつかをオブジェクト固有のメモリ操作関数に委譲しますが、これらの関数がプライベートヒープからはみ出してメモリ管理を行わないようにしています。

重要なのは、たとえユーザがいつもヒープ内のメモリブロックを指すようなオブジェクトポインタを操作しているとしても、Python 用ヒープの管理はインタプリタ自体が行うもので、ユーザがそれを制御する余地はないと理解することです。Python オブジェクトや内部使用されるバッファを入れるためのヒープ空間のメモリ確保は、必要に応じて、Python メモリマネージャがこのドキュメント内で列挙しているPython/C API 関数群を介して行います。

メモリ管理の崩壊を避けるため、拡張モジュールの作者は決して Python オブジェクトを C ライブラリが公開している関数: `malloc()` 、 `calloc()` 、 `realloc()` および `free()` で操作しようとしてはなりません。こうした関数を使うと、C のメモリ操作関数と Python メモリマネージャとの間で関数呼び出しが交錯します。 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;

この例では、I/O バッファに対するメモリ要求は C ライブラリのメモリ操作関数を使っています。Python メモリマネージャーは戻り値として返される bytes オブジェクトを確保する時にだけ必要です。

とはいえ、ほとんどの状況では、メモリの操作は Python ヒープに固定して行うよう勧めます。なぜなら、Python ヒープは Python メモリマネジャの管理下にあるからです。例えば、インタプリタを C で書かれた新たなオブジェクト型で拡張する際には、ヒープでのメモリ管理が必要です。Python ヒープを使った方がよいもう一つの理由として、拡張モジュールが必要としているメモリについて Python メモリマネージャに 情報を提供 してほしいということがあります。たとえ必要なメモリが内部的かつ非常に特化した用途に対して排他的に用いられるものだとしても、全てのメモリ操作要求を Python メモリマネージャに委譲すれば、インタプリタはより正確なメモリフットプリントの全体像を把握できます。その結果、特定の状況では、Python メモリマネージャがガベージコレクションやメモリのコンパクト化、その他何らかの予防措置といった、適切な動作をトリガできることがあります。上の例で示したように C ライブラリのメモリ操作関数を使うと、I/O バッファ用に確保したメモリは Python メモリマネージャの管理から完全に外れることに注意してください。

参考

環境変数 `PYTHONMALLOC` を使用して Python が利用するメモリアロケータを制御することができます。

環境変数 `PYTHONMALLOCSTATS` を使用して、新たなオブジェクトアリーナが生成される時と、シャットダウン時に pymalloc メモリアロケータ の統計情報を表示できます。

## Allocator Domains

All allocating functions belong to one of three different "domains" (see also `PyMemAllocatorDomain`). These domains represent different allocation strategies and are optimized for different purposes. The specific details on how every domain allocates memory or what internal functions each domain calls is considered an implementation detail, but for debugging purposes a simplified table can be found at here. The APIs used to allocate and free a block of memory must be from the same domain. For example, `PyMem_Free()` must be used to free memory allocated using `PyMem_Malloc()`.

The three allocation domains are:

- Raw domain: intended for allocating memory for general-purpose memory buffers where the allocation must go to the system allocator or where the allocator can operate without the GIL. The memory is requested directly from the system. See Raw Memory Interface.

- "Mem" domain: intended for allocating memory for Python buffers and general-purpose memory buffers where the allocation must be performed with the GIL held. The memory is taken from the Python private heap. See Memory Interface.

- Object domain: intended for allocating memory for Python objects. The memory is taken from the Python private heap. See Object allocators.

注釈

The free-threaded build requires that only Python objects are allocated using the "object" domain and that all Python objects are allocated using that domain. This differs from the prior Python versions, where this was only a best practice and not a hard requirement.

For example, buffers (non-Python objects) should be allocated using `PyMem_Malloc()`, `PyMem_RawMalloc()`, or `malloc()`, but not `PyObject_Malloc()`.

See Memory Allocation APIs.

## 生メモリインターフェース

The following function sets are wrappers to the system allocator. These functions are thread-safe, the GIL does not need to be held.

The default raw memory allocator uses the following functions: `malloc()`, `calloc()`, `realloc()` and `free()`; call `malloc(1)` (or `calloc(1, 1)`) when requesting zero bytes.

Added in version 3.4.

void *PyMem_RawMalloc(size_t n)
  次に属します: Stable ABI (バージョン 3.13 より).

  n バイトを割り当て、そのメモリを指す void* 型のポインタを返します。要求が失敗した場合 `NULL` を返します。

  0バイトを要求すると、 `PyMem_RawMalloc(1)` が呼ばれたときと同じように、可能なら `NULL` でないユニークなポインタを返します。確保されたメモリーにはいかなる初期化も行われません。

void *PyMem_RawCalloc(size_t nelem, size_t elsize)
  次に属します: Stable ABI (バージョン 3.13 より).

  各要素が elsize バイトの要素 nelem 個分のメモリーを確保し、そのメモリーを指す void* 型のポインタを返します。アロケートに失敗した場合は `NULL` を返します。確保されたメモリー領域はゼロで初期化されます。

  要素数か要素のサイズが0バイトの要求に対しては、可能なら `PyMem_RawCalloc(1, 1)` が呼ばれたのと同じように、ユニークな `NULL` でないポインタを返します。

  Added in version 3.5.

void *PyMem_RawRealloc(void *p, size_t n)
  次に属します: Stable ABI (バージョン 3.13 より).

  p が指すメモリブロックを n バイトにリサイズします。古いサイズと新しいサイズの小さい方までの内容は変更されません。

  p が `NULL` の場合呼び出しは `PyMem_RawMalloc(n)` と等価です。そうでなく、 n がゼロに等しい場合、メモリブロックはリサイズされますが解放されません。返されたポインタは非 `NULL` です。

  p が `NULL` でない限り、p はそれより前の `PyMem_RawMalloc()`, `PyMem_RawRealloc()`, `PyMem_RawCalloc()` の呼び出しにより返されなければなりません。

  要求が失敗した場合 `PyMem_RawRealloc()` は `NULL` を返し、 p は前のメモリエリアをさす有効なポインタのままです。

void PyMem_RawFree(void *p)
  次に属します: Stable ABI (バージョン 3.13 より).

  p が指すメモリブロックを解放します。 p は以前呼び出した `PyMem_RawMalloc()`, `PyMem_RawRealloc()`, `PyMem_RawCalloc()` の返した値でなければなりません。それ以外の場合や `PyMem_RawFree(p)` を呼び出した後だった場合、未定義の動作になります。

  p が `NULL` の場合何もしません。

## メモリインターフェース

以下の関数群が利用して Python ヒープに対してメモリを確保したり解放したり出来ます。これらの関数は ANSI C 標準に従ってモデル化されていますが、0 バイトを要求した際の動作についても定義しています:

The default memory allocator uses the pymalloc memory allocator.

警告

The GIL must be held when using these functions.

バージョン 3.6 で変更: デフォルトのアロケータがシステムの `malloc()` から pymalloc になりました。

void *PyMem_Malloc(size_t n)
  次に属します: Stable ABI.

  n バイトを割り当て、そのメモリを指す void* 型のポインタを返します。要求が失敗した場合 `NULL` を返します。

  0バイトを要求すると、 `PyMem_Malloc(1)` が呼ばれたときと同じように、可能なら `NULL` でないユニークなポインタを返します。 確保されたメモリーにはいかなる初期化も行われません。

void *PyMem_Calloc(size_t nelem, size_t elsize)
  次に属します: Stable ABI (バージョン 3.7 より).

  各要素が elsize バイトの要素 nelem 個分のメモリーを確保し、そのメモリーを指す void* 型のポインタを返します。アロケートに失敗した場合は `NULL` を返します。確保されたメモリー領域はゼロで初期化されます。

  要素数か要素のサイズが0バイトの要求に対しては、可能なら `PyMem_Calloc(1, 1)` が呼ばれたのと同じように、ユニークな `NULL` でないポインタを返します。

  Added in version 3.5.

void *PyMem_Realloc(void *p, size_t n)
  次に属します: Stable ABI.

  p が指すメモリブロックを n バイトにリサイズします。古いサイズと新しいサイズの小さい方までの内容は変更されません。

  p が `NULL` の場合呼び出しは `PyMem_Malloc(n)` と等価です。そうでなく、 n がゼロに等しい場合、メモリブロックはリサイズされますが解放されません。返されたポインタは非 `NULL` です。

  p が `NULL` でない限り、p はそれより前の `PyMem_Malloc()`, `PyMem_Realloc()` または `PyMem_Calloc()` の呼び出しにより返されなければなりません。

  要求が失敗した場合 `PyMem_Realloc()` は `NULL` を返し、 p は前のメモリエリアをさす有効なポインタのままです。

void PyMem_Free(void *p)
  次に属します: Stable ABI.

  p が指すメモリブロックを解放します。 p は以前呼び出した `PyMem_Malloc()`、 `PyMem_Realloc()`、または `PyMem_Calloc()` の返した値でなければなりません。それ以外の場合や `PyMem_Free(p)` を呼び出した後だった場合、未定義の動作になります。

  p が `NULL` の場合何もしません。

以下に挙げる型対象のマクロは利便性のために提供されているものです。TYPE は任意の C の型を表します。

PyMem_New(TYPE, n)

  Same as `PyMem_Malloc()`, but allocates `(n * sizeof(TYPE))` bytes of memory. Returns a pointer cast to `TYPE*`. The memory will not have been initialized in any way.

PyMem_Resize(p, TYPE, n)

  Same as `PyMem_Realloc()`, but the memory block is resized to `(n * sizeof(TYPE))` bytes. Returns a pointer cast to `TYPE*`. On return, p will be a pointer to the new memory area, or `NULL` in the event of failure.

  これは C プリプロセッサマクロです。p は常に再代入されます。エラー処理時にメモリを失うのを避けるには p の元の値を保存してください。

void PyMem_Del(void *p)

  `PyMem_Free()` と同じです。

上記に加えて、C API 関数を介することなく Python メモリ操作関数を直接呼び出すための以下のマクロセットが提供されています。ただし、これらのマクロは Python バージョン間でのバイナリ互換性を保てず、それゆえに拡張モジュールでは撤廃されているので注意してください。

- `PyMem_MALLOC(size)`

- `PyMem_NEW(type, size)`

- `PyMem_REALLOC(ptr, size)`

- `PyMem_RESIZE(ptr, type, size)`

- `PyMem_FREE(ptr)`

- `PyMem_DEL(ptr)`

## オブジェクトアロケータ

以下の関数群が利用して Python ヒープに対してメモリを確保したり解放したり出来ます。これらの関数は ANSI C 標準に従ってモデル化されていますが、0 バイトを要求した際の動作についても定義しています:

注釈

There is no guarantee that the memory returned by these allocators can be successfully cast to a Python object when intercepting the allocating functions in this domain by the methods described in the Customize Memory Allocators section.

The default object allocator uses the pymalloc memory allocator.

警告

The GIL must be held when using these functions.

void *PyObject_Malloc(size_t n)
  次に属します: Stable ABI.

  n バイトを割り当て、そのメモリを指す void* 型のポインタを返します。要求が失敗した場合 `NULL` を返します。

  0バイトを要求すると、 `PyObject_Malloc(1)` が呼ばれたときと同じように、可能なら `NULL` でないユニークなポインタを返します。 確保されたメモリーにはいかなる初期化も行われません。

void *PyObject_Calloc(size_t nelem, size_t elsize)
  次に属します: Stable ABI (バージョン 3.7 より).

  各要素が elsize バイトの要素 nelem 個分のメモリーを確保し、そのメモリーを指す void* 型のポインタを返します。アロケートに失敗した場合は `NULL` を返します。確保されたメモリー領域はゼロで初期化されます。

  要素数か要素のサイズが0バイトの要求に対しては、可能なら `PyObject_Calloc(1, 1)` が呼ばれたのと同じように、ユニークな `NULL` でないポインタを返します。

  Added in version 3.5.

void *PyObject_Realloc(void *p, size_t n)
  次に属します: Stable ABI.

  p が指すメモリブロックを n バイトにリサイズします。古いサイズと新しいサイズの小さい方までの内容は変更されません。

  p が `NULL` の場合呼び出しは `PyObject_Malloc(n)` と等価です。そうでなく、 n がゼロに等しい場合、メモリブロックはリサイズされますが解放されません。返されたポインタは非 `NULL` です。

  p が `NULL` でない限り、p はそれより前の `PyObject_Malloc()`, `PyObject_Realloc()` または `PyObject_Calloc()` の呼び出しにより返されなければなりません。

  要求が失敗した場合 `PyObject_Realloc()` は `NULL` を返し、 p は前のメモリエリアをさす有効なポインタのままです。

void PyObject_Free(void *p)
  次に属します: Stable ABI.

  p が指すメモリブロックを解放します。 p は以前呼び出した `PyObject_Malloc()`、 `PyObject_Realloc()`、または `PyObject_Calloc()` の返した値でなければなりません。それ以外の場合や `PyObject_Free(p)` を呼び出した後だった場合、未定義の動作になります。

  p が `NULL` の場合何もしません。

## Default Memory Allocators

Default memory allocators:

Configuration | 名前 | PyMem_RawMalloc | PyMem_Malloc | PyObject_Malloc
--- | --- | --- | --- | ---
リリースビルド | `"pymalloc"` | `malloc` | `pymalloc` | `pymalloc`
デバッグビルド | `"pymalloc_debug"` | `malloc` + debug | `pymalloc` + debug | `pymalloc` + debug
pymalloc 無しのリリースビルド | `"malloc"` | `malloc` | `malloc` | `malloc`
pymalloc 無しのデバッグビルド | `"malloc_debug"` | `malloc` + debug | `malloc` + debug | `malloc` + debug

説明:

- Name: value for `PYTHONMALLOC` environment variable.

- `malloc`: system allocators from the standard C library, C functions: `malloc()`, `calloc()`, `realloc()` and `free()`.

- `pymalloc`: pymalloc memory allocator.

- `mimalloc`: mimalloc memory allocator. The pymalloc allocator will be used if mimalloc support isn't available.

- "+ debug": with debug hooks on the Python memory allocators.

- "Debug build": Python build in debug mode.

## メモリアロケータをカスタマイズする

Added in version 3.4.

type PyMemAllocatorEx

  Structure used to describe a memory block allocator. The structure has the following fields:

  フィールド | 意味
  --- | ---
  `void *ctx` | 第一引数として渡されるユーザコンテキスト
  `void* malloc(void *ctx, size_t size)` | メモリブロックを割り当てます
  `void* calloc(void *ctx, size_t nelem, size_t elsize)` | 0で初期化されたメモリブロックを割り当てます
  `void* realloc(void *ctx, void *ptr, size_t new_size)` | メモリブロックを割り当てるかリサイズします
  `void free(void *ctx, void *ptr)` | メモリブロックを解放する

  バージョン 3.5 で変更: The `PyMemAllocator` structure was renamed to `PyMemAllocatorEx` and a new `calloc` field was added.

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)

  指定されたドメインのメモリブロックアロケータを設定します。

  新しいアロケータは、0バイトを要求されたときユニークな `NULL` でないポインタを返さなければなりません。

  For the `PYMEM_DOMAIN_RAW` domain, the allocator must be thread-safe: the GIL is not held when the allocator is called.

  For the remaining domains, the allocator must also be thread-safe: the allocator may be called in different interpreters that do not share a `GIL`.

  新しいアロケータがフックでない (1つ前のアロケータを呼び出さない) 場合、 `PyMem_SetupDebugHooks()` 関数を呼び出して、新しいアロケータの上にデバッグフックを再度設置しなければなりません。

  See also `PyPreConfig.allocator` and Preinitialize Python with PyPreConfig.

  警告

  `PyMem_SetAllocator()` does have the following contract:

  - It can be called after `Py_PreInitialize()` and before `Py_InitializeFromConfig()` to install a custom memory allocator. There are no restrictions over the installed allocator other than the ones imposed by the domain (for instance, the Raw Domain allows the allocator to be called without the GIL held). See the section on allocator domains for more information.

  - If called after Python has finish initializing (after `Py_InitializeFromConfig()` has been called) the allocator must wrap the existing allocator. Substituting the current allocator for some other arbitrary one is not supported.

  バージョン 3.12 で変更: All allocators must be thread-safe.

void PyMem_SetupDebugHooks(void)

  Setup debug hooks in the Python memory allocators to detect memory errors.

## Debug hooks on the Python memory allocators

When Python is built in debug mode, the `PyMem_SetupDebugHooks()` function is called at the Python preinitialization to setup debug hooks on Python memory allocators to detect memory errors.

The `PYTHONMALLOC` environment variable can be used to install debug hooks on a Python compiled in release mode (ex: `PYTHONMALLOC=debug`).

The `PyMem_SetupDebugHooks()` function can be used to set debug hooks after calling `PyMem_SetAllocator()`.

These debug hooks fill dynamically allocated memory blocks with special, recognizable bit patterns. Newly allocated memory is filled with the byte `0xCD` (`PYMEM_CLEANBYTE`), freed memory is filled with the byte `0xDD` (`PYMEM_DEADBYTE`). Memory blocks are surrounded by "forbidden bytes" filled with the byte `0xFD` (`PYMEM_FORBIDDENBYTE`). Strings of these bytes are unlikely to be valid addresses, floats, or ASCII strings.

実行時チェック:

- Detect API violations. For example, detect if `PyObject_Free()` is called on a memory block allocated by `PyMem_Malloc()`.

- Detect write before the start of the buffer (buffer underflow).

- Detect write after the end of the buffer (buffer overflow).

- Check that the GIL is held when allocator functions of `PYMEM_DOMAIN_OBJ` (ex: `PyObject_Malloc()`) and `PYMEM_DOMAIN_MEM` (ex: `PyMem_Malloc()`) domains are called.

On error, the debug hooks use the `tracemalloc` module to get the traceback where a memory block was allocated. The traceback is only displayed if `tracemalloc` is tracing Python memory allocations and the memory block was traced.

Let S = `sizeof(size_t)`. `2*S` bytes are added at each end of each block of N bytes requested. The memory layout is like so, where p represents the address returned by a malloc-like or realloc-like function (`p[i:j]` means the slice of bytes from `*(p+i)` inclusive up to `*(p+j)` exclusive; note that the treatment of negative indices differs from a Python slice):

`p[-2*S:-S]`

  Number of bytes originally asked for. This is a size_t, big-endian (easier to read in a memory dump).

`p[-S]`

  API identifier (ASCII character):

  - `'r'` for `PYMEM_DOMAIN_RAW`.

  - `'m'` for `PYMEM_DOMAIN_MEM`.

  - `'o'` for `PYMEM_DOMAIN_OBJ`.

`p[-S+1:0]`

  Copies of PYMEM_FORBIDDENBYTE. Used to catch under- writes and reads.

`p[0:N]`

  The requested memory, filled with copies of PYMEM_CLEANBYTE, used to catch reference to uninitialized memory. When a realloc-like function is called requesting a larger memory block, the new excess bytes are also filled with PYMEM_CLEANBYTE. When a free-like function is called, these are overwritten with PYMEM_DEADBYTE, to catch reference to freed memory. When a realloc- like function is called requesting a smaller memory block, the excess old bytes are also filled with PYMEM_DEADBYTE.

`p[N:N+S]`

  Copies of PYMEM_FORBIDDENBYTE. Used to catch over- writes and reads.

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

  Only used if the `PYMEM_DEBUG_SERIALNO` macro is defined (not defined by default).

  A serial number, incremented by 1 on each call to a malloc-like or realloc-like function. Big-endian `size_t`. If "bad memory" is detected later, the serial number gives an excellent way to set a breakpoint on the next run, to capture the instant at which this block was passed out. The static function bumpserialno() in obmalloc.c is the only place the serial number is incremented, and exists so you can set such a breakpoint easily.

A realloc-like or free-like function first checks that the PYMEM_FORBIDDENBYTE bytes at each end are intact. If they've been altered, diagnostic output is written to stderr, and the program is aborted via Py_FatalError(). The other main failure mode is provoking a memory error when a program reads up one of the special bit patterns and tries to use it as an address. If you get in a debugger then and look at the object, you're likely to see that it's entirely filled with PYMEM_DEADBYTE (meaning freed memory is getting used) or PYMEM_CLEANBYTE (meaning uninitialized memory is getting used).

バージョン 3.6 で変更: The `PyMem_SetupDebugHooks()` function now also works on Python compiled in release mode. On error, the debug hooks now use `tracemalloc` to get the traceback where a memory block was allocated. The debug hooks now also check if the GIL is held when functions of `PYMEM_DOMAIN_OBJ` and `PYMEM_DOMAIN_MEM` domains are called.

バージョン 3.8 で変更: Byte patterns `0xCB` (`PYMEM_CLEANBYTE`), `0xDB` (`PYMEM_DEADBYTE`) and `0xFB` (`PYMEM_FORBIDDENBYTE`) have been replaced with `0xCD`, `0xDD` and `0xFD` to use the same values than Windows CRT debug `malloc()` and `free()`.

## pymalloc アロケータ

Python has a pymalloc allocator optimized for small objects (smaller or equal to 512 bytes) with a short lifetime. It uses memory mappings called "arenas" with a fixed size of either 256 KiB on 32-bit platforms or 1 MiB on 64-bit platforms. It falls back to `PyMem_RawMalloc()` and `PyMem_RawRealloc()` for allocations larger than 512 bytes.

pymalloc is the default allocator of the `PYMEM_DOMAIN_MEM` (ex: `PyMem_Malloc()`) and `PYMEM_DOMAIN_OBJ` (ex: `PyObject_Malloc()`) domains.

アリーナアロケータは、次の関数を使います:

- `VirtualAlloc()` and `VirtualFree()` on Windows,

- `mmap()` and `munmap()` if available,

- それ以外の場合は `malloc()` と `free()`。

This allocator is disabled if Python is configured with the `--without-pymalloc` option. It can also be disabled at runtime using the `PYTHONMALLOC` environment variable (ex: `PYTHONMALLOC=malloc`).

Typically, it makes sense to disable the pymalloc allocator when building Python with AddressSanitizer (`--with-address-sanitizer`) which helps uncover low level bugs within the C code.

### pymalloc アリーナアロケータのカスタマイズ

Added in version 3.4.

type PyObjectArenaAllocator

  アリーナアロケータを記述するための構造体です。3つのフィールドを持ちます:

  フィールド | 意味
  --- | ---
  `void *ctx` | 第一引数として渡されるユーザコンテキスト
  `void* alloc(void *ctx, size_t size)` | size バイトのアリーナを割り当てます
  `void free(void *ctx, void *ptr, size_t size)` | アリーナを解放します

void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator)

  アリーナアロケータを取得します。

void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator)

  アリーナアロケータを設定します。

## The mimalloc allocator

Added in version 3.13.

Python supports the mimalloc allocator when the underlying platform support is available. mimalloc "is a general purpose allocator with excellent performance characteristics. Initially developed by Daan Leijen for the runtime systems of the Koka and Lean languages."

## tracemalloc C API

Added in version 3.7.

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

  Track an allocated memory block in the `tracemalloc` module.

  Return `0` on success, return `-1` on error (failed to allocate memory to store the trace). Return `-2` if tracemalloc is disabled.

  If memory block is already tracked, update the existing trace.

int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)

  Untrack an allocated memory block in the `tracemalloc` module. Do nothing if the block was not tracked.

  Return `-2` if tracemalloc is disabled, otherwise return `0`.

## 使用例

最初に述べた関数セットを使って、 概要 節の例を Python ヒープに I/O バッファをメモリ確保するように書き換えたものを以下に示します:

    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 ファミリを使って行うことが必要です。以下のコードには二つのエラーがあり、そのうちの一つには異なるヒープを操作する別のメモリ操作関数を混用しているので 致命的 (Fatal) とラベルづけをしています。

    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()  */

In addition to the functions aimed at handling raw memory blocks from the Python heap, objects in Python are allocated and released with `PyObject_New`, `PyObject_NewVar` and `PyObject_Del()`.

これらの関数については、次章の C による新しいオブジェクト型の定義や実装に関する記述の中で説明します。