メモリ管理
**********


概要
====

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 メモリアロケータ の統
  計情報を表示できます。


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

以下の関数群はシステムのアロケータをラップします。 これらの関数はスレ
ッドセーフで、 *GIL* を保持していなくても呼び出すことができます。

デフォルトの 生メモリアロケーター は次の関数を利用します: "malloc()",
"calloc()", "realloc()", "free()" 0バイトを要求されたときには
"malloc(1)" (あるいは "calloc(1, 1)") を呼びます。

バージョン 3.4 で追加.

void* PyMem_RawMalloc(size_t n)

   Allocates *n* bytes and returns a pointer of type "void*" to the
   allocated memory, or "NULL" if the request fails.

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

void* PyMem_RawCalloc(size_t nelem, size_t elsize)

   Allocates *nelem* elements each whose size in bytes is *elsize* and
   returns a pointer of type "void*" to the allocated memory, or
   "NULL" if the request fails. The memory is initialized to zeros.

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

   バージョン 3.5 で追加.

void* PyMem_RawRealloc(void *p, size_t n)

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

   *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.

警告:

  これらの関数を呼ぶときには、 *GIL* を保持しておく必要があります。

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

void* PyMem_Malloc(size_t n)

   Allocates *n* bytes and returns a pointer of type "void*" to the
   allocated memory, or "NULL" if the request fails.

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

void* PyMem_Calloc(size_t nelem, size_t elsize)

   Allocates *nelem* elements each whose size in bytes is *elsize* and
   returns a pointer of type "void*" to the allocated memory, or
   "NULL" if the request fails. The memory is initialized to zeros.

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

   バージョン 3.5 で追加.

void* PyMem_Realloc(void *p, size_t n)

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

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

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

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

TYPE* PyMem_New(TYPE, size_t 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.

TYPE* PyMem_Resize(void *p, TYPE, size_t 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 バイトを要求した際の動作についても定義しています:

The default object allocator uses the pymalloc memory allocator.

警告:

  これらの関数を呼ぶときには、 *GIL* を保持しておく必要があります。

void* PyObject_Malloc(size_t n)

   Allocates *n* bytes and returns a pointer of type "void*" to the
   allocated memory, or "NULL" if the request fails.

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

void* PyObject_Calloc(size_t nelem, size_t elsize)

   Allocates *nelem* elements each whose size in bytes is *elsize* and
   returns a pointer of type "void*" to the allocated memory, or
   "NULL" if the request fails. The memory is initialized to zeros.

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

   バージョン 3.5 で追加.

void* PyObject_Realloc(void *p, size_t n)

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

   *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     |
+---------------------------------+----------------------+--------------------+-----------------------+----------------------+

説明:

* 名前: "PYTHONMALLOC" 環境変数の値

* "malloc": 標準 C ライブラリのシステムアロケータ、C 関数: "malloc()",
  "calloc()", "realloc()", "free()"

* "pymalloc": pymalloc メモリアロケータ

* "+ debug": "PyMem_SetupDebugHooks()" で設置されるデバッグフックとの
  組み合わせ


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

バージョン 3.4 で追加.

PyMemAllocatorEx

   メモリブロックアロケータを記述するための構造体です。4つのフィールド
   を持ちます:

   +------------------------------------------------------------+-----------------------------------------+
   | フィールド                                                 | 意味                                    |
   |============================================================|=========================================|
   | "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 で変更: "PyMemAllocator" 構造体が "PyMemAllocatorEx"
   にリネームされた上で "calloc" フィールドが追加されました。

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" でない
   ポインタを返さなければなりません。

   "PYMEM_DOMAIN_RAW" ドメインでは、アロケータはスレッドセーフでなけれ
   ばなりません: アロケータが呼び出されたとき *GIL* は保持されていませ
   ん。

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

void PyMem_SetupDebugHooks(void)

   Python メモリアロケータ関数のバグを検出するためのフックを設定します
   。

   Newly allocated memory is filled with the byte "0xCD"
   ("CLEANBYTE"), freed memory is filled with the byte "0xDD"
   ("DEADBYTE"). Memory blocks are surrounded by "forbidden bytes"
   ("FORBIDDENBYTE": byte "0xFD").

   実行時チェック:

   * API 違反を検出します。例: "PyMem_Malloc()" が割り当てたバッファに
     対して "PyObject_Free()" を呼びだした。

   * バッファの開始前の書き込み (バッファアンダーフロー) を検出します

   * バッファ終了後の書き込み (バッファオーバーフロー) を検出します

   * 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.

   These hooks are installed by default if Python is compiled in debug
   mode. The "PYTHONMALLOC" environment variable can be used to
   install debug hooks on a Python compiled in release mode.

   バージョン 3.6 で変更: This 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" ("CLEANBYTE"), "0xDB"
   ("DEADBYTE") and "0xFB" ("FORBIDDENBYTE") have been replaced with
   "0xCD", "0xDD" and "0xFD" to use the same values than Windows CRT
   debug "malloc()" and "free()".


pymalloc アロケータ
===================

Python には、寿命の短いの小さな(512バイト以下の)オブジェクトに最適化さ
れた *pymalloc* アロケータがあります。 *pymalloc* は、256 KiBの固定サ
イズの "アリーナ" と呼びれるメモリマッピングを使います。512バイトより
も大きな割り当てでは、 "PyMem_RawMalloc()" と "PyMem_RawRealloc()" に
フォールバックします。

*pymalloc* は、"PYMEM_DOMAIN_MEM" (ex: "PyMem_Malloc()") と
"PYMEM_DOMAIN_OBJ" (ex: "PyObject_Malloc()") ドメインの 既定のアロケー
タ です。

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

* Windows では "VirtualAlloc()" と "VirtualFree()"、

* 利用できる場合、"mmap()" と "munmap()"、

* それ以外の場合は "malloc()" と "free()"。


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

バージョン 3.4 で追加.

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)

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


tracemalloc C API
=================

バージョン 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()  */

素のメモリブロックを Python ヒープ上で操作する関数に加え、
"PyObject_New()" 、 "PyObject_NewVar()" 、および "PyObject_Del()" を使
うと、 Python におけるオブジェクトをメモリ確保したり解放したりできます
。

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