4

さて、どうやらこれはうまくいく:

void foo(size_t s) {
    int myArray[s];
    // ... use myArray...
}

これは本当に合法ですか?つまり、コンパイルするためです(Cコンパイラが非定数として拒否する場合)。私の質問の最初の部分は次のとおりです。これはどのように機能しますか? スタックに割り当てていると思いますか?これは使用とは異なりalloca()ますか?

実際には、これを行うコードをいくつか見つけました。

void bar(size_t chunkSize) {
    CFReadStreamRef foo = NULL;
    // ...some stuff to init foo...

    while (stuffToDo) {
        UInt8 buffer[chunkSize];
        // ...read some data from stream into buffer
        //    using CFReadStreamRead()...
    }
}

これは機能します。fooただし、バッファーの割り当てをループ内から関数の最初の行 (が宣言される直前) に移動すると、関数は... 動作を停止します。デバッガーでは、ローカル変数の最初のアクセスに到達し、その後...終了します。スローされる例外は見られず、クラッシュせず、プログラムが実行を続けるだけです (実際には、関数は文字列を返し、その戻り値はNULL、戻り変数が初期化されるものです)。何が起こっているのかわかりません。私の質問の 2 番目の部分は、最初の部分に照らして、一体何が起こっているのかということです。

4

1 に答える 1

3

危ないけどC99では合法、そうみたいallocaです。

これは alloca に似ているため、スタックに割り当てるときに適切なサイズの配列が必要です。長さがゼロの場合にこれが定義されているかどうかはわかりませんが、配列が「十分に大きい」場合、スタックオーバーフローが確実に発生する可能性があります。

何が起こっているかについては、サイズが妥当であれば、ループから引き抜いても違いはありません。パラメータ値が大きすぎる (またはおそらく 0) ため、未定義の動作が発生していると思われchunkSizeます。パラメータを検証する必要があります。アセンブリは、それをループから引き出すと違いが生じる理由を教えてくれます (プログラム内の他のすべてが整形式であると仮定します)。

于 2012-08-10T19:40:30.897 に答える