6

バッファオーバーランの場合、プログラムはいつクラッシュしますか

#include<stdio.h>
#include<stdlib.h>

main() {
    char buff[50];
    int i=0;
    for( i=0; i <100; i++ )
    {
        buff[i] = i;
        printf("buff[%d]=%d\n",i,buff[i]);
    }
}

割り当てられた最初の 50 バイトはどうなりますか? プログラムがクラッシュするのはいつですか?

gcc a.out を使用した UBUNTU で、i 99 のときにクラッシュしていることがわかります

>>
buff[99]=99
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)
<<

for ループの buff[51] で割り当てが発生したときに、これがクラッシュしない理由を知りたいですか?

4

2 に答える 2

13

これは未定義の動作です。いつクラッシュするか(またはクラッシュするかどうか) を予測することはできませんが、「クラッシュしない」ことに依存してアプリケーションをコーディングすることはできません。

推論

理論的根拠は、c 配列にはコンパイル時または実行時の「範囲外のインデックスのチェック」がないためです。これは、他の高水準言語のSTL ベクトルまたは配列に存在します。したがって、プログラムが割り当てられた範囲を超えてメモリにアクセスするときはいつでも、それが単にプログラムのスタック上の別のフィールドを破壊するのか、別のプログラムのメモリなどに影響を与えるのかに依存するため、極端な場合にのみ発生するクラッシュを予測することはできません。OSが強制的に介入する状態でのみクラッシュするか、プログラムが正しく機能しなくなった場合にのみクラッシュします。

関数呼び出しの中にいて、配列のすぐ隣に RETURN アドレス、つまり、プログラムが呼び出し元の関数に戻るために使用するアドレスがあるとします。あなたがそれを壊して、今度はあなたのプログラムが有効なアドレスではない壊れた値に戻ろうとしているとします。したがって、そのような状況ではクラッシュします。

最悪の事態は、別のフィールドの値を黙って変更し、クラッシュが発生していないと仮定して何が問題なのかさえ発見できなかった場合に発生します。

于 2013-10-10T10:50:57.250 に答える
1

スタックにバッファを割り当てたように見えるので、おそらく for ループのコードのどこかで、実行される命令を最初に上書きしたときにアプリがクラッシュする可能性があります...少なくともそれが想定されている方法です理論的になる。

于 2013-10-10T10:53:36.310 に答える