私はこれがコンパイルを拒否することを発見しました:
int test_alloc_stack(int size){
if(0) goto error; // same issue whatever conditional is used
int apply[size];
give_values(apply,size);
return 1;
error:
return 0;
}
私が得るエラーは次のとおりです:「可変的に変更されたタイプの識別子のスコープにジャンプします」。 「goto」で行を削除し、エラーにジャンプすると、問題が解決します。
適用に動的割り当てを使用すると、問題も解消されます。これは正常にコンパイルされます:
int test_alloc_heap(int size){
if(0) goto error;
int * apply = calloc(sizeof(int),size);
give_values(apply,size);
free(apply);
return 1;
error : return 0;
}
何が起こっている ?
宣言:
int apply[size];
可変長配列を作成します。スコープ外になると、コンパイラはその配列の割り当てをクリーンアップするコードを生成する必要があります。このようなオブジェクトのスコープにジャンプすることは禁止されています。一部の実装では、クリーンアップコードに必要な初期化を調整する必要があり、スコープにジャンプすると初期化がバイパスされるためです。
動的割り当てに変更した場合、コンパイラーではなく、初期化とクリーンアップがユーザーの責任になります。
それは標準によって禁止されています:
C99標準、パラグラフ6.8.6.1
制約
[...] gotoステートメントは、可変的に変更された型を持つ識別子のスコープの外側からその識別子のスコープの内側にジャンプしてはなりません。
これはまさにあなたのgoto
が行っていることです。つまり、apply
のスコープの外側から内側にジャンプします。
次の回避策を使用して、apply
の範囲を制限できます。
if(0) goto error;
{
int apply[size];
give_values(apply,size);
return 1;
}
error:
return 0;
goto
を使用すると、(実行時に)apply
を割り当てる行をスキップできます。
次の4つの方法のいずれかで問題を解決できます。
1:gotoを使用しないようにコードを書き直します。
2:apply
の宣言をgoto
の前に移動します。
3:スコープを変更してerror:
はapply
の範囲外です:
int test_alloc_stack(int size){
if(0) goto error; // same issue whatever conditional is used
{
int apply[size];
give_values(apply,size);
return 1;
}
error:
return 0;
}
4:変数宣言を変更して、コンパイル時にサイズを決定できるようにします。