0

配列オーバーフローを引き起こすコードを試してみましたが、gcc でコンパイルすると予期しないことが起こりました。以下はコードです:

#include <stdio.h>

int main(int argc, const char *argv[])
{
    int a[] = {0,2,4,7};
    int size = sizeof(a)/sizeof(int);
    int i;
    printf("%d, %X\n", size, &a);
    a[4] = 6;
    printf("%d, %X\n", size, &a);
    a[5] = 78;
    printf("%d, %X\n", size, &a);
    a[6] = 65;
    printf("%d, %X\n", size, &a);
    for (i = 0; i < size; i++) {
        printf("%d, ", a[i]);
    }
    printf("%d, %d, %d\n", a[size], a[size+1], a[size+2]);
    printf("\n");
    return 0;
}

結果は次のとおりです。

4, BFC4DDF8
6, BFC4DDF8
6, BFC4DDF8
6, BFC4DDF8
0, 2, 4, 7, 6, 5, 65, 0, 0

そのため、コードではサイズの値を変更しませんでしたが、実行すると自動的に変更されました! では、なぜこれが起こるのか誰か教えてもらえますか?

PS: gcc のバージョンは 4.8.0 です。

@NPEの回答によると、のアドレスを確認するsizeと、実際にはの直後にメモリに配置されますa

しかし、コードを追加すると

printf("%X\n", &size);

printf("%d, %X\n", size, &a);

結果は

BFC39108
4, BFC3910C
4, BFC3910C
4, BFC3910C
4, BFC3910C
0, 2, 4, 7, 4, 78, 65

このとき、sizeは の直前にメモリに配置されますa


実際、私が さんの住所をどこに印刷してもsize、それは さんの住所のすぐ前に位置していaます。のアドレスを出力しないとsize、のアドレスの直後に配置されaます。それでも、コンパイラの未定義の動作ですか?

4

2 に答える 2

4

の最後を超えて書いているためa、プログラムには未定義の動作があります。これは、あなたが観察している方法を含め、好きなように振る舞うことができることを意味します。

実際に起こっていることは、それsizeがたまたまメモリ内の の直後に配置されていることaと、次の範囲外の割り当てです。

a[4] = 6;

上書きしますsize

別のコンパイラまたは別のコンパイラ設定を使用したり、一見取るに足らない変更をプログラムに加えたりすると、コードが他の方法で失敗する可能性があることに注意してください。または、テスト全体でうまく機能し、顧客の前で爆発する可能性があります。

于 2013-04-05T13:54:24.863 に答える
0

a[] 配列の末尾を超えてメモリを上書きしたため、サイズの値が上書きされました。

于 2013-04-05T13:54:34.233 に答える