1

第 1 章で、K&R は関数 copy を次のように紹介します。

void copy(char to[], char from[]) {
/* copy from from[] to to[], assumes sufficient space */
    int i = 0;
    while ((to[i] = from[i]) != '\0') {
        i++;
    }
}

この関数を少しいじってみると、予想外の結果が得られました。プログラム例:

int main() {
    char a[3] = {'h', 'a', '\n'};
    char b[3];
    printf("a: %s", a); // prints ha
    copy(b, a);
    printf("a: %s", a); // prints nothing
    printf("b: %s", b); // prints ha

    return 0;
}

今私の質問に:

  1. からのコピーが機能するaのはなぜですか?「\0」が含まれていなくbても、コピーの while ループが終了するのはなぜですか?a

  2. なぜa突然変異するのですか?

4

5 に答える 5

3

バッファ オーバーフローが発生している可能性があります。

aが適切に終了していない ( がない\0) ため、が見つからない限り、からにcopyコピーされます。したがって、より多くのバイトが書き込まれ、オーバーフローします (プラットフォームに依存する、未定義の動作)。ab\0ba

オーバーフローする部分は\0afteraであり、a長さゼロの文字列になります。

スタックはおそらく次のようになります。

                        b        a        
[ arbitrary memory ][ 0 0 0 ][ h a \n ][ 0 ? ? ? ? ]

?不明なデータを示します。これは、何がそこにあるかわからず、どこにも指定されていないためです。しかし、 が必要であることがわかっています。0そうしないと、よりprintf多くのガベージが出力されます。

copyの後にゼロが見つかるまでコピーしますa。偶然、 0の末尾にa がaあり、それが にコピーされbます。bは からのコンテンツですでに満たされているため、 はにaオーバーフローba、スタックは次のようになります。

                        b         a
[ arbitrary memory ][ h a \n ][ 0 a \n ][ 0 ? ? ? ? ]

\0先頭に があるためa、は空であるとprintf見なされます。a

于 2013-08-20T15:08:08.353 に答える