最適化コンパイラの世界へようこそ!
as-ifルールのため、コンパイラは、元のコードと同じ観察可能な結果を持つものを作成するだけで済みます。 ので、コンパイラが自由に場合:
- は未使用のアレイ
- が空ループ
- スタックの主要外部から動的配列を格納削除 - 主にのみ呼び出さなければならない特殊な機能であるため一度環境
あなたは、スタックオーバーフローを観察したい場合(悪いものではなく、私たちの素敵なサイト:-))、 あなたべきによって:
- 私はのように正確にすることができますように書いた何をすべきか、コンパイラを伝えるために
- を外し、すべての最適化とpreferentlyデバッグモードでコンパイルの配列を埋めるためにいくつかのコードを使用し
次のコードは、とSIGSEGVを行います打ち鳴らす3.4.1 cc -g foo.c -o foo
#include <stdio.h>
#define SIZE 88388608
void fill(int *arr, size_t size, int val) {
for (size_t i=0; i<size; i++) {
arr[i] = val;
}
}
int main() {
int arr[SIZE];
int arr1[SIZE];
int arr2[SIZE];
fill(arr, SIZE, 0);
fill(arr1, SIZE, 0);
fill(arr2, SIZE, 0);
printf("%d %d %d\n", arr[12], arr1[15], arr2[18]);
return 0;
}
としてコンパイルと-O2
最適化レベルとしてコンパイルされた場合でも、このコードは正常に動作します...コンパイラは、今にしています私にとっては賢明で、実際に実行されるものを理解する唯一の真の方法であるアセンブリコードを徹底的に調べるのに十分な勇気はありません!
スタックをオーバーフローさせたときに、*未定義の動作*が発生し、期待通りに動作しないように見えることがあります。また、最近のコンパイラはかなりスマートです。これらの配列は使用されていないので、なぜコンパイラが実際にそれらのためのスペースを作成する必要がありますか? –
arの型を 'int'から' volatile int'に変更するとどうなりますか? –
また、AFAIKはスタックのサイズがシステムによって異なる場合があります。 –