#
9.1 概要

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 = PyString_FromString(buf);
        free(buf); /* malloc'ed */
        return res;

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

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