メモリー管理命令
メモリー管理命令を次の表に示します。
命令 | 従来型の構文 | 自由形式構文 |
---|---|---|
記憶域の割り振り | ALLOC (記憶域の割り振り) | %ALLOC (記憶域の割り振り) |
記憶域の解放 | DEALLOC (記憶域の解放) | |
記憶域の再割り振り | REALLOC (新しい長さでの記憶域の再割り振り) | %REALLOC (記憶域の再割り振り) |
変数のアドレスの入手 | %ADDR (変数のアドレスの検索) | |
プロシージャーのアドレスの入手 | %PADDR (プロシージャー・アドレスの検索) |
ALLOC 命令では、動的記憶域を割り振り、結果フィールド・ポインターを、 その記憶域を指し示すように設定します。 この記憶域は初期化されません。
REALLOC 命令は、結果フィールド・ポインターによって指し示されている 動的記憶域の長さを変更します。 新しい記憶域は、割り振られると、古い記憶域の値に初期化されます。 新しいサイズが古いサイズより小さい場合、データが切り捨てられます。 新しいサイズが古いサイズより大きい場合は、コピーされたデータの後の 記憶域は初期化されません。 古い記憶域は解放されます。 結果フィールド・ポインターは、新しい記憶域を指し示すように設定 されます。
DEALLOC 命令では、結果フィールド・ポインターが設定される 動的記憶域を解放します。 操作拡張 (N) が指定されている場合、ポインターは再割り振りが正常に 行われた後、*NULL に設定されます。
記憶域は、活動化グループが終了すると暗黙に解放されます。 LR をオンに設定すると、モジュールによって割り振られた 動的記憶域は解放されませんが、動的記憶域を指し示すポインターは失われます。
ヒープ記憶域には、単一レベルとテラスペースの 2 つのタイプがあります。 制御仕様書で ALLOC キーワードを使用して、 メモリー管理命令が使用するヒープ記憶域のタイプを制御できます。
ヒープ記憶域のそれぞれのタイプに、利点と欠点があります。
- 個別の割り振りまたは再割り振りの最大サイズは、テラスペース・ヒープ記憶域のほうが大きくなります。
- %ALLOC 組み込み関数および %REALLOC 組み込み関数に対する RPG の許容最大サイズは、4294967295 バイトです。 単一レベル・ヒープ記憶域を使用するとき、RPG の許容最大サイズは 16776704 バイトです。
- メモリー管理命令がテラスペース・ヒープ記憶域を使用することをコンパイラーがコンパイル時に検出できると、 ALLOC および REALLOC の命令コードに対する RPG の許容最大サイズは 4294967295 バイトに上がります。 RPG メモリー管理命令が単一レベル・ヒープ記憶域を使用する場合、 またはコンパイラーがコンパイル時にヒープ記憶域のタイプを検出できない場合には、 16776704 バイトという小さいほうの限度が有効になります。
- 実行時にヒープ記憶域が使用可能であるかどうかによって、実際の割り振り可能最大サイズが、 RPG の許容最大サイズより小さくなることがあります。
- テラスペース・ヒープ記憶域の再割り振りと割り振り解除に RPG が使用するシステム関数では、 単一レベル・ヒープ記憶域およびテラスペース・ヒープ記憶域へのポインターを処理できます。 ポインターの再割り振りにテラスペース再割り振り関数が使用されると、 その新しい割り振りのヒープ記憶域タイプは、元の割り振りと同じになります。
- 単一レベル・ヒープ記憶域の再割り振りと割り振り解除に RPG が使用するシステム関数では、 単一レベル・ヒープ記憶域へのポインターしか処理できません。
- 単一レベル記憶域のほうが、テラスペース記憶域より保全性を高くすることができます。 例えば、記憶域オーバーランで影響を受ける可能性がある記憶域は、単一レベル記憶域を使用するとメガバイト単位ですが、 テラスペース記憶域の場合にはテラバイト単位になります。
さまざまなタイプのヒープ記憶域について 詳しくは、「ILE 概念」(>SC41-5606) の記憶域管理に関する章を参照してください。
動的記憶域の使用を誤ると、問題が発生する原因となります。 以下の例は、
それを回避するための手順を示したものです。
D Fld1 S 25A BASED(Ptr1)
D Fld2 S 5A BASED(Ptr2)
D Ptr1 S *
D Ptr2 S *
....
C ALLOC 25 Ptr1
C DEALLOC Ptr1
* この時点以降、Fld1 にはアクセスすることはできません。基底ポインター
* Ptr1 が、割り振られた記憶域を指さなくなっているからです。
C CALL 'SOMEPGM'
* 'SOMEPGM' への直前の呼び出し中に、いくつかの記憶割り振りが
* 行われている可能性があります。この場合、次の割り当てを行うことは
* 非常に危険です。これは、25 バイトの記憶域が
* 'a' によって埋め込まれるためです。その記憶域が現在何に使用されているかを
* 知ることができなくなります。
C EVAL Fld1 = *ALL'a'
以下は、さらに深刻な状況です。
- ポインターが、再割り振りまたは割り振り解除の前にコピーされた場合、 同様のエラーが起こる可能性があります。 ポインターを割り振り済みの記憶域にコピーする場合は、十分に注意して、 そのポインターが、記憶域の割り振り解除後や再割り振り後に使用されることが ないようにしてください。
- 動的記憶域を指し示すポインターがコピーされると、そのコピーが 記憶域の割り振り解除または再割り振りに使用される場合があります。 この場合、元のポインターは、それが新しい値に設定されるまでは 使用してはなりません。
- 動的記憶域を指し示すポインターがパラメーターとして渡されると、 呼び出される側が、その記憶域を割り振り解除したり、再割り振りしたりする 可能性があります。 呼び出しが戻った後で、そのポインターを使用してその記憶域にアクセスしようと すると問題が起こります。
- 動的記憶域を指し示すポインターが *INZSR 内で設定されると、 それ以降にそのポインターが RESET されたときに、 もはや割り振られていない記憶域にそのポインターが設定される可能性が あります。
- 動的記憶域を指し示すポインターが失われた場合 (例えば、クリアされた ことによって、あるいは ALLOC 命令によって新しいポインターに設定 された場合など) には、また別の種類の問題が起こる可能性があります。 ポインターが失われてしまうと、それが指し示している記憶域は解放することができません。システムは、この記憶域がもはやアドレス可能ではなくなっていることを認識していないために、この記憶域を割り振ることはできません。この記憶域は、活動化グループが終了するまで解放されません。