メモリ管理
メモリ管理:インデックス への移動
このヘルプ トピックでは、さまざまなターゲット プラットフォームで使用される 2 つのメモリ マネージャについて説明し、変数のメモリ関連の問題についても簡単に説明します。
目次
デフォルトのメモリ マネージャ
使用されるメモリ マネージャはアプリケーションのターゲット プラットフォーム/コンパイラで決まります。
各プラットフォームのデフォルト メモリ マネージャの一覧を次の表に示します。
プラットフォーム | コンパイラ | メモリ マネージャ名 |
---|---|---|
Win32 |
FastMM(GETMEM.inc) | |
Win64 |
FastMM(GETMEM.inc) | |
OSX64 |
Posix/64 | |
OSXARM64 |
Posix/64 | |
LINUX64 |
Posix/64 | |
iOS デバイス 64 ビット |
POSIX/64 | |
iOSSimARM64 |
POSIX/64 | |
Android |
POSIX/32 | |
ANDROID64 |
POSIX/64 |
FastMM メモリ マネージャ(Win32 および Win64)
このメモリ マネージャは、アプリケーションでの動的なメモリ割り当ておよび割り当て解除をすべて管理します。System の標準手続き New、Dispose、GetMem、ReallocMem、FreeMem では、このメモリ マネージャを使用します。オブジェクト、動的配列、長い文字列はすべて、このメモリ マネージャを通じて割り当てられます。
Win32 と Win64 の場合、デフォルトの FastMM メモリ マネージャは、小サイズから中サイズまでのメモリ ブロックを多数割り当てるアプリケーションに最適化されています。オブジェクト指向アプリケーションや文字列データを処理するアプリケーションがその典型です。このメモリ マネージャは、シングルスレッドおよびマルチスレッド アプリケーションで(高速でメモリ オーバーヘッドが少ない)効率的な処理を行えるように最適化されています。その他のメモリ マネージャ(Windows での GlobalAlloc、LocalAlloc、プライベート ヒープ サポートの実装など)を直接使用すると、通常そのような状況ではよく機能せず、アプリケーションの処理速度が低下するでしょう。
最高のパフォーマンスを確保するため、このメモリ マネージャでは仮想メモリ API(VirtualAlloc 関数および VirtualFree 関数)と直接やり取りします。
Win32 の場合、このメモリ マネージャでは、最大 2 GB までのユーザー モード アドレス空間をサポートします。
メモ: ユーザー モード アドレス空間を 3 GB に増やすには、「メモリ アドレス空間の拡張」を参照してください。
メモリ マネージャのメモリ ブロックは、4 バイトの倍数のサイズに切り上げられており、4 バイトのヘッダーを含んでいます。このヘッダーには、ブロック サイズやその他のステータス ビットが格納されています。メモリ ブロックの開始アドレスは、少なくとも 8 バイト境界、オプションによっては 16 バイト境界で整列されるため、メモリ ブロックのアドレス指定時のパフォーマンスが向上します。System.SetMinimumBlockAlignment を参照してください。
Win64 の場合、このメモリ マネージャでは、理論上最大 16 EiB までのユーザー モード アドレス空間をサポートします。
メモ: 実際の割り当て可能な最大サイズは、CPU の実装とオペレーティング システムによって異なります。 たとえば、現行の Intel/X64 実装では最大 256 TiB(48 ビット)までをサポートしており、Windows 7 Professional では最大 192 GiB までをサポートしています。
メモリ マネージャのメモリ ブロックは、16 バイトの倍数のサイズに切り上げられており、8 バイトのヘッダーを含んでいます。このヘッダーには、ブロック サイズやその他のステータス ビットが格納されています。メモリ ブロックの開始アドレスは、少なくとも 16 バイトの境界で整列されます。
Win32 および Win64 の場合、メモリ マネージャでは、将来メモリ ブロックが再割り当てされることを予想して、そのような再割り当て操作に通常伴うパフォーマンスへの影響を軽減するアルゴリズムを採用しています。この再割り当てアルゴリズムは、アドレス空間の断片化を軽減するうえでも役に立ちます。メモリ マネージャでは、外部 DLL を使用する必要がない共有メカニズムを提供します。
メモリ マネージャには、アプリケーションが自身のメモリ使用状況と潜在的なメモリ リークを監視するのに役立つレポート機能が用意されています。
メモリ マネージャは、GetMemoryManagerState と GetMemoryMap という 2 つの手続きを提供しています。これらを利用して、アプリケーションは、メモリ マネージャのステータス情報や詳細なメモリ使用マップを取得できます。
POSIX メモリ マネージャ(POSIX プラットフォーム)
POSIX メモリ マネージャが使用されるのは、ターゲット プラットフォーム/コンパイラが、macOS 64 ビット、macOS ARM 64 ビット、Linux 64 ビット、iOS Device 64 ビット、iOS シミュレータ ARM 64 ビット、Android 32 ビット、Android 64 ビットの場合です。
すべてのメモリ管理関数/メソッドでは、次の表に示すように、POSIX システム ライブラリを使用しています。
RTL | POSIX 関数 |
---|---|
変数
グローバル変数は、アプリケーションのデータ セグメントに割り当てられ、プログラムの実行中は存続し続けます。手続きや関数の中で宣言された変数はローカル変数と呼ばれ、アプリケーションのスタックに保持されます。手続きや関数が呼び出されるたびにローカル変数が割り当てられ、終了時にローカル変数は廃棄されます。コンパイラの最適化によって、変数が早い段階で破棄されることもあります。
Win32 では、アプリケーションのスタックは、最小スタック サイズと最大スタック サイズの 2 つの値で定義されます。この 2 つの値は $MINSTACKSIZE と $MAXSTACKSIZE コンパイラ指令によって制御されます。それぞれのデフォルト値は 16,384(16K)と 1,048,576(1MB)です。アプリケーションは最小スタック サイズを利用できるように保証されています。また、アプリケーションのスタックが最大スタック サイズより大きくなることは決してありません。アプリケーションの最小スタック サイズ要件を満たす十分なメモリが利用できない場合は、そのアプリケーションを起動しようとすると Windows からエラーが出されます。
Win32 アプリケーションで、最小スタック サイズで指定されているよりも多くのスタック領域が必要な場合は、追加のメモリが 4K 単位で自動的に割り当てられます。 追加メモリが利用できないか、スタックの合計サイズが最大スタック サイズを超えるため、追加スタック領域の割り当てに失敗した場合は、EStackOverflow 例外が生成されます (スタック オーバーフローのチェックは完全に自動化されています。 従来スタック オーバーフロー チェックを制御していた $S コンパイラ指令は、下位互換性のために残されています)。
GetMem または New 手続きで作成した動的変数はヒープに割り当てられ、FreeMem または Dispose で割り当てを解除されるまで存続します。
長い文字列、ワイド文字列、動的配列、バリアント、およびインターフェイスはヒープに割り当てられますが、それらのメモリは自動的に管理されます。