17.3. メモリ管理

Table of Contents
SPI_copytuple -- 上位エグゼキュータのコンテキスト内にタプルのコピーを作成します。
SPI_copytupledesc -- 上位エグゼキュータのコンテキスト内にタプル記述子のコピーを作成します。
SPI_copytupleintoslot -- 上位エグゼキュータ内にタプルと記述子のコピーを作成します。
SPI_modifytuple -- 与えられたタプルの選択されたフィールドを置き換えたタプルを作成します。
SPI_palloc -- 上位エクゼキュータのコンテキスト内にメモリを割り当てます。
SPI_repalloc -- 上位エクゼキュータ内のメモリの再割り当てを行います。
SPI_pfree -- 上位エグゼキュータ内のメモリを解放します。
SPI_freetuple -- 上位エグゼキュータのコンテキスト内に割り当てられたタプルを解放します。
SPI_freetuptable -- SPI_exec や同種の関数で作成されたタプルセットを解放します。
SPI_freeplan -- 以前の保存された計画を解放します。

PostgreSQL はメモリコンテキスト内にメモリを確保します。 そこでは、異なる有効期間毎に異なる領域になされた割り当てを便利に管理する方法を提供します。コンテキストの削除は、そこに割り当てられたメモリを全て解放します。このように、メモリリークを防ぐために個々のオブジェクトを追跡し続ける必要はありません。 管理しなければならないコンテキスト数は相対的に少なくなります。 palloc や関連する関数は、現在の"current" からメモリを割り当てます。

SPI_connect は新規にメモリコンテキストを割り当て、それを現在のものにします。SPI_finish は前回の現在のメモリコンテキストを戻し、SPI_connectで作成された現在のコンテキストを削除します。プロシージャ内で行われた一時的なメモリ割り当てがプロシージャの終了時に、メモリリークがなく、再利用されることを、この動作は保証します。

しかし、プロシージャが割り当てられた (参照渡しのデータ型の値など) メモリオブジェクトを返す必要がある場合、少なくとも SPI に接続していない時に、palloc を使用して返すオブジェクトを割り当てることはできません。試みると、そのオブジェクトはSPI_finish 時に割り当て解除されますので、そのプロシージャの動作は信頼できないものになります。

この問題を解決するには、返すオブジェクトの割り当てに SPI_palloc を使用して下さい。SPI_palloc"ユーザエグゼキュータ"メモリ、つまり、SPI_connect が呼び出された時の現在のメモリコンテキストであり、プロシージャの戻り値用のコンテキストとしてまさに正しいところ、に領域を割り当てます。

SPI に接続していない状態で呼び出した場合、SPI_palloc は通常の pallocと同じ動作をします。

プロシージャがSPI マネージャに接続する前では、現在のメモリコンテキストは、上位のエグゼキュータのコンテキストです。 ですので、palloc 経由でそのプロシージャによる、または、SPI ユーティリティ関数による割り当ては全て、このコンテキスト内に作成されます。

SPI_connect が呼び出された後、現在のコンテキストは、SPI_connect により作成されたそのプロシージャ固有のコンテキストになります。palloc/repalloc 経由で、または、(SPI_copytuple,SPI_copytupledesc,SPI_copytupleintoslot,SPI_modifytuple,および SPI_pallocを除く)SPIユーティリティ関数によって作成された、全ての割り当てはこのコンテキスト内に作成されます。

プロシージャがSPIマネージャとの接続を(SPI_finishを使用して)閉じた時、現在のコンテキストは上位のエグゼキュータのコンテキストに戻され、そのプロシージャのメモリコンテキスト内で作成された全ての割り当ては解放され、そして、それ以降使用できなくなります!

この節で説明した全ての関数は接続、未接続状態のプロシージャの両方から使用することができます。未接続のプロシージャでは、それらは(palloc などの)その背後にある、通常のバックエンド関数と同じ動作をします。