Jim Trevor のPL クラスの「 Cyclone: A safe dialect of C 」を読みながら、C と Cyclone を理解しようとしています。Trevor は、安全でない go-to ステートメントの例を次のように示しています。
int z;
{ int x = 0xBAD; goto L; }
{ int *y = &z;
L: *y = 3; // Possible segfault
}
Trevor は、上記のコードの安全性の問題を次のように説明しています。
多くのコンパイラは、ブロックに入るときにブロックのローカル変数をスタックに割り当て、ブロックが出るときにストレージの割り当てを解除 (ポップ) します (ただし、これは C 標準では義務付けられていません)。例をこのようにコンパイルすると、プログラムが最初のブロックに入ると、x のスペースがスタックに割り当てられ、値 0xBAD で初期化されます。goto は、2 番目のブロックの中央にジャンプし、ポインター y の内容への代入に直接ジャンプします。y は 2 番目のブロックで宣言された最初の (唯一の) 変数であるため、割り当てでは y がスタックの一番上にあると想定されます。残念ながら、それはまさに x が割り当てられた場所であるため、プログラムは場所 0xBAD に書き込もうとし、おそらくセグメンテーション違反を引き起こします。
go to
ここでその発言が問題になる理由がわかりません。問題は、初期化されていないポインター Z からの予測できない動作であるようint * y
ですint* y
。 Z によって参照されるメモリ。Trevor の論文が Z と X の両方が何らかの形で 0xBAD を参照することを暗示している理由がわかりません。C は最初のブロックの新しいスタック フレームを作成しませんか (Trevor が説明したように): したがって、メモリ内の新しいフレームに 0xBAD を書き込みます (Z によって参照されるメモリ内の場所ではありません)。