0

真剣に..私は80年代の古いハッカーであり、手に余裕を持って、大騒ぎが何であるかを「C」と思っていました。

(私のバックグラウンドはForthで、これは後ろから前に物事を行うので、多くのエラーを強制することについて多くを学びます)

この場合、サイズが3要素(0,1,2)になると思った小さな配列を設定しました。

コンパイルを実行すると、範囲外のエラーが発生したと思いますが、コンパイルは正常に実行され、正常に実行されます。

これは大急ぎではありませんが、小さなハゲの場所には良くありません。


int main()
{
    char members[3][16];  // 3 elements, each 15 char long plus null

    printf("\n enter something..  ");
    scanf( "%s", members[4]);

    printf("\n and something else..  ");
    scanf( "%s", members[5]);

    printf(" %s  ", members[4]);
    printf(" %s\n", members[5]);

    return 0;
}
4

4 に答える 4

5

範囲外の配列にアクセスすると、未定義の動作が発生します。これは、明らかなエラーなしで実行することを含め、何かが起こる可能性があることを意味します。

于 2012-07-21T09:50:06.327 に答える
3

C は境界チェックを行いません。(Forth もそうではないので、期待がどこから来たのかわかりません。)

配列のオーバーフローは未定義の動作です。クラッシュすることは許可されていますが、必須ではありません。この場合、バイトはたまたま、ローカル変数が配置されたスタック フレームと同じ仮想メモリ ページにあります。フレームがページの終わりに近づいている場合、CPU は不正なアドレスを認識し、オーバーフローについて文句を言います。

数キロバイトまたはメガバイトを外に出すと、期待どおりの結果が得られる可能性があります。

于 2012-07-21T09:51:57.323 に答える
0

通常、メモリは 4 kB ページで割り当てられます。したがって、最後の変数の後に余分なスペースがあり、バッファ オーバーランは検出されません。ただし、members配列の後に別の変数があり、に書き込むとmembers[4]、その別の変数が破損します。

valgrind や dmalloc などのツールは、バッファ オーバーランの検出によく使用されます。それらは、変数の周りに特別な保護領域を割り当て、そこに誰も書き込まれていないことを確認することで機能します。

于 2012-07-21T09:51:30.440 に答える
0

スタック上のメインの戻りアドレスを見逃して、プログラムがクラッシュしないように、メインの呼び出し元の重要ではないデータを上書きする可能性があります。さらに、一部のプラットフォーム (powerpc など) では、関数呼び出しにスタックが使用されず、戻りアドレスが特殊レジスタに格納されます (必要なときにスタックにプッシュされます)。したがって、この不正なプログラムがクラッシュしないのは正常です。

更新:さらに、一部のシステムスタックが(より高いアドレスに)成長します。少なくとも ARM スタックの成長は選択可能です。

于 2012-07-21T10:08:12.747 に答える