メモリ管理
概要
Pythonのメモリ管理には、すべてのPythonオブジェクトとデータ構造を含むプライベートヒープが含まれます。 このプライベートヒープの管理は、 Pythonメモリマネージャーによって内部的に保証されます。 Pythonメモリマネージャーには、共有、セグメンテーション、事前割り当て、キャッシュなど、さまざまな動的ストレージ管理の側面を処理するさまざまなコンポーネントがあります。
最下位レベルでは、rawメモリアロケータは、オペレーティングシステムのメモリマネージャと対話することにより、すべてのPython関連データを格納するための十分なスペースがプライベートヒープにあることを保証します。 生のメモリアロケータに加えて、複数のオブジェクト固有のアロケータが同じヒープ上で動作し、すべてのオブジェクトタイプの特性に適合した個別のメモリ管理ポリシーを実装します。 たとえば、整数は異なるストレージ要件と速度/スペースのトレードオフを意味するため、整数オブジェクトは、文字列、タプル、またはディクショナリとは異なる方法でヒープ内で管理されます。 したがって、Pythonメモリマネージャーは一部の作業をオブジェクト固有のアロケーターに委任しますが、後者がプライベートヒープの範囲内で動作することを保証します。
Pythonヒープの管理はインタプリタ自体によって実行され、そのヒープ内のメモリブロックへのオブジェクトポインタを定期的に操作する場合でも、ユーザーはそれを制御できないことを理解することが重要です。 Pythonオブジェクトおよびその他の内部バッファーへのヒープスペースの割り当ては、このドキュメントに記載されているPython / C API関数を介して、Pythonメモリマネージャーによってオンデマンドで実行されます。
メモリの破損を防ぐために、拡張機能の作成者は、Cライブラリによってエクスポートされた関数malloc()
、calloc()
、realloc()
、free()
を使用して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メモリマネージャは、結果として返されるバイトオブジェクトの割り当てにのみ関与します。
ただし、ほとんどの場合、Pythonヒープからメモリを割り当てることをお勧めします。これは、PythonヒープがPythonメモリマネージャーの制御下にあるためです。 たとえば、これは、インタプリタがCで記述された新しいオブジェクトタイプで拡張されている場合に必要です。 Pythonヒープを使用するもう1つの理由は、拡張モジュールのメモリニーズについてPythonメモリマネージャに通知したいという要望です。 要求されたメモリが内部の非常に特殊な目的にのみ使用される場合でも、すべてのメモリ要求をPythonメモリマネージャに委任すると、インタプリタはメモリフットプリント全体のより正確なイメージを得ることができます。 その結果、特定の状況下では、Pythonメモリマネージャーは、ガベージコレクション、メモリ圧縮、その他の予防手順などの適切なアクションをトリガーする場合とトリガーしない場合があります。 前の例で示したようにCライブラリアロケータを使用すると、I / Oバッファに割り当てられたメモリがPythonメモリマネージャから完全にエスケープされることに注意してください。
も参照してください
PYTHONMALLOC 環境変数を使用して、Pythonで使用されるメモリアロケータを構成できます。
PYTHONMALLOCSTATS 環境変数を使用して、新しいpymallocオブジェクトアリーナが作成されるたびに、およびシャットダウン時に、 pymallocメモリアロケータの統計を出力できます。
アロケータドメイン
すべての割り当て関数は、3つの異なる「ドメイン」のいずれかに属します( PyMemAllocatorDomain も参照)。 これらのドメインはさまざまな割り当て戦略を表しており、さまざまな目的に合わせて最適化されています。 すべてのドメインがメモリを割り当てる方法または各ドメインが呼び出す内部関数に関する具体的な詳細は、実装の詳細と見なされますが、デバッグの目的で、簡略化された表がここにあります。 特定のドメインに属する割り当て関数によって返されたメモリを、そのドメインによって示唆された目的のためだけに使用するという厳しい要件はありません(ただし、これは推奨される方法です)。 たとえば、Pythonオブジェクトを割り当てるために PyMem_RawMalloc()によって返されるメモリを使用したり、バッファにメモリを割り当てるために PyObject_Malloc()によって返されるメモリを使用したりできます。
3つの割り当てドメインは次のとおりです。
- 生のドメイン:割り当てがシステムアロケータに行く必要がある必要がある、またはアロケータが GIL なしで動作できる汎用メモリバッファにメモリを割り当てることを目的としています。 メモリはシステムに直接要求されます。
- 「mem」ドメイン: GIL を保持したまま割り当てを実行する必要があるPythonバッファおよび汎用メモリバッファにメモリを割り当てることを目的としています。 メモリはPythonプライベートヒープから取得されます。
- オブジェクトドメイン:Pythonオブジェクトに属するメモリを割り当てることを目的としています。 メモリはPythonプライベートヒープから取得されます。
特定のドメインに属する割り当て関数によって以前に割り当てられたメモリを解放するときは、一致する特定の割り当て解除関数を使用する必要があります。 たとえば、 PyMem_Free()を使用して、 PyMem_Malloc()を使用して割り当てられたメモリを解放する必要があります。
Rawメモリインターフェイス
次の関数セットは、システムアロケータのラッパーです。 これらの関数はスレッドセーフであり、 GIL を保持する必要はありません。
デフォルトのrawメモリアロケータは、次の関数を使用します:malloc()
、calloc()
、realloc()
、およびfree()
; ゼロバイトを要求するときは、malloc(1)
(またはcalloc(1, 1)
)を呼び出します。
バージョン3.4の新機能。
- void *PyMem_RawMalloc(size_t n)
n バイトを割り当て、割り当てられたメモリにタイプ void * のポインタを返します。要求が失敗した場合は、
NULL
を返します。ゼロバイトを要求すると、
PyMem_RawMalloc(1)
が代わりに呼び出されたかのように、可能であれば、別個の非NULL
ポインタが返されます。 メモリはいかなる方法でも初期化されていません。
- void *PyMem_RawCalloc(size_t nelem, size_t elsize)
バイト単位のサイズが elsize である nelem 要素を割り当て、割り当てられたメモリにタイプ void * のポインタを返します。割り当てられたメモリの場合は、
NULL
を返します。リクエストは失敗します。 メモリはゼロに初期化されます。ゼロ要素またはサイズがゼロバイトの要素を要求すると、代わりに
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
でない限り、 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メモリアロケータを使用します。
バージョン3.6で変更:デフォルトのアロケータは、システムmalloc()
ではなくpymallocになりました。
- void *PyMem_Malloc(size_t n)
n バイトを割り当て、割り当てられたメモリにタイプ void * のポインタを返します。要求が失敗した場合は、
NULL
を返します。ゼロバイトを要求すると、
PyMem_Malloc(1)
が代わりに呼び出されたかのように、可能であれば、別個の非NULL
ポインタが返されます。 メモリはいかなる方法でも初期化されていません。
- void *PyMem_Calloc(size_t nelem, size_t elsize)
バイト単位のサイズが elsize である nelem 要素を割り当て、割り当てられたメモリにタイプ void * のポインタを返します。割り当てられたメモリの場合は、
NULL
を返します。リクエストは失敗します。 メモリはゼロに初期化されます。ゼロ要素またはサイズがゼロバイトの要素を要求すると、代わりに
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
でない限り、 PyMem_Malloc()、 PyMem_Realloc()、または PyMem_Callocへの前回の呼び出しによって返されている必要があります。 ()。要求が失敗した場合、 PyMem_Realloc()は
NULL
を返し、 p は前のメモリ領域への有効なポインタのままです。
- void PyMem_Free(void *p)
p が指すメモリブロックを解放します。これは、 PyMem_Malloc()、 PyMem_Realloc()、または PyMem_Calloc( )。 それ以外の場合、または
PyMem_Free(p)
が以前に呼び出された場合、未定義の動作が発生します。p が
NULL
の場合、操作は実行されません。
以下のタイプ指向のマクロは、便宜上提供されています。 TYPE は任意のCタイプを指すことに注意してください。
- TYPE *PyMem_New(TYPE, size_t n)
- PyMem_Malloc()と同じですが、
(n * sizeof(TYPE))
バイトのメモリを割り当てます。 TYPE * にキャストされたポインタを返します。 メモリはいかなる方法でも初期化されていません。
- TYPE *PyMem_Resize(void *p, TYPE, size_t n)
PyMem_Realloc()と同じですが、メモリブロックのサイズが
(n * sizeof(TYPE))
バイトに変更されます。 TYPE * にキャストされたポインタを返します。 戻ると、 p は新しいメモリ領域へのポインタになり、障害が発生した場合はNULL
になります。これは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)
オブジェクトアロケータ
次の関数セットは、ANSI C標準をモデルにしていますが、ゼロバイトを要求するときの動作を指定しており、Pythonヒープからメモリを割り当てたり解放したりするために使用できます。
ノート
メモリアロケータのカスタマイズセクションで説明されているメソッドによってこのドメインの割り当て関数をインターセプトするときに、これらのアロケータによって返されるメモリがPythonオブジェクトに正常にキャストできるという保証はありません。
デフォルトのオブジェクトアロケータは、 pymallocメモリアロケータを使用します。
- void *PyObject_Malloc(size_t n)
n バイトを割り当て、割り当てられたメモリにタイプ void * のポインタを返します。要求が失敗した場合は、
NULL
を返します。ゼロバイトを要求すると、
PyObject_Malloc(1)
が代わりに呼び出されたかのように、可能であれば、別個の非NULL
ポインタが返されます。 メモリはいかなる方法でも初期化されていません。
- void *PyObject_Calloc(size_t nelem, size_t elsize)
バイト単位のサイズが elsize である nelem 要素を割り当て、割り当てられたメモリにタイプ void * のポインタを返します。割り当てられたメモリの場合は、
NULL
を返します。リクエストは失敗します。 メモリはゼロに初期化されます。ゼロ要素またはサイズがゼロバイトの要素を要求すると、代わりに
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
でない限り、 PyObject_Malloc()、 PyObject_Realloc()、または PyObject_Callocへの前回の呼び出しによって返されている必要があります。 ()。要求が失敗した場合、 PyObject_Realloc()は
NULL
を返し、 p は前のメモリ領域への有効なポインタのままです。
- void PyObject_Free(void *p)
p が指すメモリブロックを解放します。これは、 PyObject_Malloc()、 PyObject_Realloc()、または PyObject_Calloc( )。 それ以外の場合、または
PyObject_Free(p)
が以前に呼び出された場合、未定義の動作が発生します。p が
NULL
の場合、操作は実行されません。
デフォルトのメモリアロケータ
デフォルトのメモリアロケータ:
構成 | 名前 | 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メモリアロケータ。- 「+ debug」:Pythonメモリアロケータのデバッグフックを使用します。
- 「デバッグビルド」:デバッグモードでのPythonビルド。
メモリアロケータをカスタマイズする
バージョン3.4の新機能。
- type PyMemAllocatorEx
メモリブロックアロケータを記述するために使用される構造。 構造には4つのフィールドがあります。
分野
意味
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
関数:
- PYMEM_DOMAIN_RAW
- void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
- 指定されたドメインのメモリブロックアロケータを取得します。
- void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
指定したドメインのメモリブロックアロケータを設定します。
新しいアロケータは、ゼロバイトを要求するときに、
NULL
以外の個別のポインタを返す必要があります。PYMEM_DOMAIN_RAW
ドメインの場合、アロケータはスレッドセーフである必要があります。 GIL は、アロケータが呼び出されたときに保持されません。新しいアロケータがフックではない場合(前のアロケータを呼び出さない場合)、 PyMem_SetupDebugHooks()関数を呼び出して、新しいアロケータの上部にデバッグフックを再インストールする必要があります。
- void PyMem_SetupDebugHooks(void)
- Pythonメモリアロケータにデバッグフックを設定して、メモリエラーを検出します。
Pythonメモリアロケータのデバッグフック
Pythonがデバッグモードで構築されている場合、 PyMem_SetupDebugHooks()関数が Python preinitialization で呼び出され、Pythonメモリアロケータにデバッグフックを設定してメモリエラーを検出します。
PYTHONMALLOC 環境変数を使用して、リリースモードでコンパイルされたPythonにデバッグフックをインストールできます(例:PYTHONMALLOC=debug
)。
PyMem_SetupDebugHooks()関数は、 PyMem_SetAllocator()を呼び出した後にデバッグフックを設定するために使用できます。
これらのデバッグフックは、動的に割り当てられたメモリブロックを特別な認識可能なビットパターンで埋めます。 新しく割り当てられたメモリはバイト0xCD
(PYMEM_CLEANBYTE
)で満たされ、解放されたメモリはバイト0xDD
(PYMEM_DEADBYTE
)で満たされます。 メモリブロックは、バイト0xFD
(PYMEM_FORBIDDENBYTE
)で満たされた「禁止バイト」で囲まれています。 これらのバイトの文字列は、有効なアドレス、浮動小数点数、またはASCII文字列である可能性は低いです。
ランタイムチェック:
- API違反を検出します。 たとえば、 PyMem_Malloc()によって割り当てられたメモリブロックで PyObject_Free()が呼び出されたかどうかを検出します。
- バッファの開始前に書き込みを検出します(バッファアンダーフロー)。
- バッファの終了後の書き込みを検出します(バッファオーバーフロー)。
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、ビッグエンディアンです(メモリダンプでの読み取りが簡単です)。
p[-S]
API識別子(ASCII文字):
PYMEM_DOMAIN_RAW
の場合は'r'
。PYMEM_DOMAIN_MEM
の場合は'm'
。PYMEM_DOMAIN_OBJ
の場合は'o'
。
p[-S+1:0]
PYMEM_FORBIDDENBYTEのコピー。 アンダーライトと読み取りをキャッチするために使用されます。
p[0:N]
PYMEM_CLEANBYTEのコピーで満たされた要求されたメモリは、初期化されていないメモリへの参照をキャッチするために使用されます。 より大きなメモリブロックを要求するreallocのような関数が呼び出されると、新しい余分なバイトもPYMEM_CLEANBYTEで埋められます。 free-like関数が呼び出されると、これらはPYMEM_DEADBYTEで上書きされ、解放されたメモリへの参照をキャッチします。 より小さなメモリブロックを要求するreallocのような関数が呼び出されると、余分な古いバイトもPYMEM_DEADBYTEで埋められます。
p[N:N+S]
PYMEM_FORBIDDENBYTEのコピー。 上書きと読み取りをキャッチするために使用されます。
p[N+S:N+2*S]
PYMEM_DEBUG_SERIALNO
マクロが定義されている場合にのみ使用されます(デフォルトでは定義されていません)。mallocのような関数またはreallocのような関数を呼び出すたびに1ずつ増加するシリアル番号。 ビッグエンディアン
size_t
。 後で「不良メモリ」が検出された場合、シリアル番号は、このブロックが渡された瞬間をキャプチャするために、次の実行でブレークポイントを設定するための優れた方法を提供します。 obmalloc.cの静的関数bumpserialno()は、シリアル番号がインクリメントされる唯一の場所であり、そのようなブレークポイントを簡単に設定できるように存在します。
reallocのような関数またはfreeのような関数は、最初に両端のPYMEM_FORBIDDENBYTEバイトが無傷であることを確認します。 それらが変更されている場合、診断出力はstderrに書き込まれ、プログラムはPy_FatalError()を介して中止されます。 もう1つの主な障害モードは、プログラムが特殊なビットパターンの1つを読み取り、それをアドレスとして使用しようとしたときにメモリエラーを引き起こすことです。 デバッガーに入ってオブジェクトを見ると、オブジェクトがPYMEM_DEADBYTE(解放されたメモリが使用されていることを意味します)またはPYMEM_CLEANBYTE(初期化されていないメモリが使用されていることを意味します)で完全に満たされていることがわかります。
バージョン3.6で変更: PyMem_SetupDebugHooks()関数は、リリースモードでコンパイルされたPythonでも機能するようになりました。 エラー時に、デバッグフックは tracemalloc を使用して、メモリブロックが割り当てられたトレースバックを取得するようになりました。 デバッグフックは、PYMEM_DOMAIN_OBJ
およびPYMEM_DOMAIN_MEM
ドメインの関数が呼び出されたときにGILが保持されているかどうかもチェックするようになりました。
バージョン3.8で変更:バイトパターン0xCB
(PYMEM_CLEANBYTE
)、0xDB
(PYMEM_DEADBYTE
)および0xFB
( PYMEM_FORBIDDENBYTE
)は0xCD
、0xDD
、0xFD
に置き換えられ、WindowsCRTデバッグmalloc()
およびfree()
。
pymallocアロケータ
Pythonには、寿命の短い小さなオブジェクト(512バイト以下)用に最適化された pymalloc アロケータがあります。 256KiBの固定サイズの「アリーナ」と呼ばれるメモリマッピングを使用します。 512バイトを超える割り当ての場合は、 PyMem_RawMalloc()および PyMem_RawRealloc()にフォールバックします。
pymalloc は、PYMEM_DOMAIN_MEM
(例: PyMem_Malloc())およびPYMEM_DOMAIN_OBJ
(例:のデフォルトアロケータです。 ] PyObject_Malloc())ドメイン。
アリーナアロケーターは次の機能を使用します。
- Windowsの
VirtualAlloc()
およびVirtualFree()
、 mmap()
およびmunmap()
が利用可能な場合、- それ以外の場合は、
malloc()
およびfree()
。
Pythonが-without-pymalloc オプションで構成されている場合、このアロケーターは無効になります。 PYTHONMALLOC 環境変数(例:PYTHONMALLOC=malloc
)を使用して、実行時に無効にすることもできます。
pymalloc ArenaAllocatorをカスタマイズする
バージョン3.4の新機能。
- type PyObjectArenaAllocator
アリーナアロケーターを説明するために使用される構造。 構造には3つのフィールドがあります。
分野
意味
void *ctx
最初の引数として渡されたユーザーコンテキスト
void* alloc(void *ctx, size_t 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)
tracemalloc モジュールで割り当てられたメモリブロックを追跡します。
成功した場合は
0
を返し、エラーの場合は-1
を返します(トレースを格納するためのメモリの割り当てに失敗しました)。 tracemallocが無効になっている場合は、-2
を返します。メモリブロックがすでに追跡されている場合は、既存のトレースを更新します。
- int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
tracemalloc モジュールで割り当てられたメモリブロックのトラックを解除します。 ブロックが追跡されなかった場合は何もしません。
tracemallocが無効になっている場合は
-2
を返し、それ以外の場合は0
を返します。
例
これはセクション概要の例で、最初の関数セットを使用してI / Oバッファーが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;
上記の2つの例では、バッファーは常に同じセットに属する関数を介して操作されることに注意してください。 実際、特定のメモリブロックに同じメモリAPIファミリを使用する必要があるため、異なるアロケータが混在するリスクが最小限に抑えられます。 次のコードシーケンスには2つのエラーが含まれ、そのうちの1つは、異なるヒープで動作する2つの異なるアロケータが混在しているため、 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ヒープからのrawメモリブロックの処理を目的とした関数に加えて、Pythonのオブジェクトは、 PyObject_New()、 PyObject_NewVar()、および PyObject_Del()で割り当ておよび解放されます。 。
これらについては、Cでの新しいオブジェクトタイプの定義と実装に関する次の章で説明します。