0

Java や C# などの言語のコンパイラは、(確実に) まだ割り当て/初期化されていないローカル変数を使用しようとすると、エラーを出します。

その機能がコンパイラにどのように実装されているのだろうか。明らかに、変数の初期化ステータスに関する情報はブール値フラグとして保存でき、代入ステートメントが検出された後にそれに応じて設定できます。しかし、ループ本体や条件ステートメントのような (ネストされた) サブスコープはどうでしょうか?

4

2 に答える 2

2

これは、生存情報を計算することで実現できます。

コンパイラは通常、ソース コードを低レベルの中間表現 (IR) に変換し、そのコードを基本ブロック (ジャンプレス コード) に分割し、そこから制御フロー グラフ (CFG) を構築します。

活性分析は、基本ブロックごとに LiveOut セットを計算できます。変数がいくつかの基本ブロックの LiveOut セットにある場合、その変数は、削除される (割り当てられる) 前に後続のブロックで使用されることを意味します。

CFG には、ENTRY ノードと EXIT ノードの 2 つの特別なノードがあります。変数が ENTRY ノードの LiveOut セットにある場合、それは変数が値に割り当てられる前に使用されることを意味します。

ポインターは、この分析を複雑にする可能性があります。たとえば、次のコードを考えてみましょう

 int *p, x, y;
 ...
 *p = 123;
 y = x*2;

誤検知を報告しないために、コンパイラはPointer-analysisと呼ばれるものを実行する必要があります。この分析が行うことは、ポインターが指す可能性がある (または指す必要がある) 可能性のあるターゲットのセットを各ポインターに対して計算することです。上記の例で、コンパイラが p が x を指していることを発見した場合、x は次の行で使用されるときに初期化されていません。

于 2015-06-25T14:55:52.517 に答える
0

これは比較的簡単です。可能なすべてのコード実行パスは、変数を使用する前に割り当てにつながる必要があります。ループも可能なパスとして扱われます。この種の分析では、繰り返しは問題になりません。

于 2015-06-24T18:58:24.070 に答える