クラッシュすると予想されるプログラムがありますが、クラッシュしません。理由を教えてください。
char a[5];
strncpy(a,"abcdefg",7);
a[7] = '\0';
printf("%s\n",a);
の配列サイズより大きいstrncpy()
でプログラムがクラッシュするべきではありません。として出力されます。gcc コンパイラを使用しています。a[7]='\0'
5
abcedefg
配列のサイズは 5で、バッファ オーバーランchar a[5];
の問題である 7 番目の場所に割り当てており、コードの動作は実行時に未定義です。
strncpy(a,"abcdefg",7);
a[7] = '\0';
どちらも間違っています。次のように配列を定義する必要があります。
#defined size 9 // greater then > 7
char a[size];
null char"abcdefg"
には 8 char が 1 つ余分に必要であることに注意してください。\0
あなたの例では、a
プログラムのスタックが高くなる可能性があるため、プログラムは (配列の開始アドレス) + 5 を超えてメモリにアクセスできます。したがって、コードは機能しますが、理想的には未定義の動作です。
C では、(特に) 何か間違ったことをした場合でも、自分が何をしているかを知っていると想定することがよくあります。配列に境界はありません。運が良ければ、未定義のメモリ位置に入り、セグメンテーション違反が発生した場合にのみエラーが発生します。そうしないと、結果がどうであれ、変更メモリにアクセスできます。
crash すべきであると述べて試みているため、未定義の動作に定義を与えることはできません。一般的にクラッシュしない未定義の動作の別の例は、 とint x = INT_MAX + 1;
です。偶然だとしても、これらはあなたのシステムで動作するかもしれません。だからといって、彼らが他のシステムに大混乱をもたらすのを止めることはできません!int x = 0; x = x++ + ++x;
「無色の緑色のアイデアは猛烈に眠る」または「タイプライターは象を暗闇に追いやった」と考えてください。これらのステートメントのいずれかは、英語で意味を成しますか? それらをどのように解釈しますか?これは、C 実装が未定義の動作を処理する方法と同様の状況です。
少なくとも12 個の卵を保管できるカートンに 42 個の卵を入れるように依頼されたら、どうなるか考えてみましょう。コンテナには間違いなく境界がありますが、すべてがそこに収まると主張します。コンテナには 12 個の卵しか保管できないことがわかりました。残りの 30 個の卵がどうなるかわからないため、動作は未定義です。