7

C ++で、実行スレッドが遭遇することのないローカル変数宣言にスタックスペースが割り当てられるのはなぜですか?または、C ++標準で定義されていない場合、特定のコンパイラが実行スレッドで検出されないローカル変数宣言にスタックスペースを割り当てるのはなぜですか?コンパイラーは、実行スレッドが検出した変数宣言にのみスタックスペースを割り当てても機能しますか?

たとえば、変数charが検出されないデバッグモードでこの関数を呼び出すと、スタックオーバーフローが発生します。

void f()
{
    if (false)
    {
        char chars[INT_MAX];
    }
}
4

5 に答える 5

8

コンパイラーはローカル変数の宣言を上げました。これが行われるかどうかは標準で定義されていないため、動作は実装固有です。そうすることで、すべてのローカル変数用のスペースを一度に割り当てることができ、オーバーヘッドが削減されます。

ただし、最適化を行うと、コンパイラーは特定のケースをデッドコードとして識別し、発生しているものは排除されます。

于 2012-04-12T16:39:09.387 に答える
6

1)そうしない理由はありません。C ++標準は、実行中に入力されないスコープ内の変数にスペースが割り当てられないことを約束していません。

2)より速くて簡単です。すべてのローカルが一度に割り当てられる場合、ローカルにスペースを割り当てるためのコードは、関数の最初のスタックポインターへの1回の更新と、最後の1回の更新で構成されます。スコープ内のローカルをそのスコープの最初と最後で割り当ておよび割り当て解除する必要がある場合は、より多くのスタックポインターの更新を取得します。

于 2012-04-12T16:45:11.793 に答える
4

これは、コンパイラと最適化レベルに大きく依存します。一部のコンパイラは、そこにあるifブロックに到達することは決してないため、そのためのコードをまったく出力しないことを通知できます。他の人はそうするでしょう。その他は、最適化レベルに依存する場合があります。さらに、計算が「簡単」であるため、スコープが入力されたときではなく、関数が呼び出されたときにすべてのローカル変数にスペースを割り当てるものもあります。これは実際にはバニラCの動作に似ています。これは、関数の先頭ですべての変数を宣言する必要があるためです(スコープをスコープローカル変数で囲むことがバニラCに存在するかどうかはわかりませんが、長い間使用されていました)。それから。

また、スタックがヒープよりもはるかに小さいこと、およびローカル変数宣言がその容量を超える可能性があることに明らかに遭遇していますが、それがあなたの例の意図であると確信しています。

より良い「なぜ彼らがそれをしたのか」を探しているなら、これに使用しているコンパイラのバージョン(および設定)を投稿してください。おそらく、作成者の1人が応答します。それがなければ、誰が知っていますか?

于 2012-04-12T16:43:23.310 に答える
0

MSVCの場合、未使用のローカル変数でコンパイラ警告(C4101)が発行されます。詳細については、http: //msdn.microsoft.com/en-us/library/c733d5h9 (v = vs.80).aspxをご覧ください。

于 2012-04-12T17:02:32.600 に答える
0

コンパイラと使用する設定によって異なります。たとえば(VS 2008で実際にコンパイルされるようにこれを変更する必要がありました)、次の場合、デバッグではスタックオーバーフロー例外がスローされますが、リリースでは終了します。

void f()
{
    if (false)
    {
        char chars[INT_MAX/2];
    }
}

int main(int argc, _TCHAR* argv[])
{
    f();
    return 0;
}
于 2012-04-12T17:02:37.853 に答える