1
//SECTION I:
void main()
{
    char str[5] = "12345";  //---a)
    char str[5] = "1234";   //---b)
    cout<<"String is: "<<str<<endl;
}
Output: a) Error: Array bounds Overflow.
        b) 1234

//SECTION II:
void main()
{
    char str[5];
    cout<<"Enter String: ";
    cin>>str;
    cout<<"String is: "<<str<<endl;
}

さまざまな入力文字列を試してみましたが、驚いたことに、奇妙な結果が得られました。

ケースI:入力文字列:1234、出力:1234(これは予想される動作であるため、問題ありません)

ケースII:入力文字列:12345、出力:12345(コンパイラによってエラーは報告されませんが、エラーを予期していました:配列境界オーバーフロー。)

ケースIII:入力文字列:123456、出力:123456(コンパイラによってエラーは報告されませんでしたが、エラーを予期していました:配列境界オーバーフロー。)

................................................。

................................................。

ケースVI:入力文字列:123456789、出力:123456789(エラー:処理されていない例外。アクセス違反。)

私の疑問は、セクションIで容量よりも多くの文字を割り当てたときに、コンパイラがエラーを報告したことです。配列の境界がオーバーフローしました。

しかし、セクションIIで同じことを試しても、エラーは発生しません。なんでそうなの?注意:これはVisualStudioで実行しました

4

6 に答える 6

4
char str[5] = "12345";

これはコンパイル時のエラーです。サイズ5の配列に、長さ6の文字列(追加されたnull終了に注意)を割り当てます。


char str[5];
cin>>str; 

これにより、ランタイムエラーが発生する可能性があります。入力する文字列の長さによっては、提供するバッファ(サイズ5)が小さすぎる場合があります(ここでもnull終了に注意してください)。


もちろん、コンパイラは実行時にユーザー入力をチェックすることはできません。運が良ければ、セグメンテーション違反によってこのようなアクセス違反が通知されます。本当に、何でも起こり得ます。

アクセス違反で例外をスローすることは必須ではありません。これに対処するには、配列境界チェックを自分で実装するか、または(おそらくより良い)必要に応じてサイズを適応させるコンテナクラスがあります(std::string):

std::string str;
cin >> str;
于 2012-04-24T11:24:44.937 に答える
4

あなたが見ているのは未定義の振る舞いです。範囲外の配列を書き込んでいます。その場合、何かが発生する可能性があります(期待する出力を確認することを含む)。

于 2012-04-24T11:26:14.703 に答える
3

さまざまな入力文字列を試してみましたが、驚いたことに、奇妙な結果が得られました。

この現象は未定義動作(UB)と呼ばれます。

配列が保持できるよりも多くの文字を入力するとすぐに、charUBを招待します。
時々、それは動作するかもしれません、それはいつか動作しないかもしれません、それはクラッシュするかもしれません。要するに、明確なパターンはありません。

[補足:コンパイラがコンパイルを許可void main()している場合、それは標準に準拠していません。]

于 2012-04-24T11:25:32.923 に答える
2

2番目のケースでは、コンパイラが認識できないためです。実行時にのみ、バグがあります。C / C ++はデフォルトでランタイム境界チェックを提供しないため、エラーは認識されませんが、プログラムを「中断」します。ただし、このブレークはすぐに表示される必要はありませんが、strは固定数のバイトのみが予約されているメモリ内の場所を指しますが、とにかくさらにバイトを書き込むだけです。

プログラムの動作は未定義になります。通常、そしてまたあなたの特定のケースでは、それは機能し続けるかもしれません、そしてあなたは他のいくつかのコンポーネントの記憶を上書きするでしょう。禁止されているメモリにアクセスするために大量の書き込みを行うと(または同じメモリを2回解放すると)、プログラムがクラッシュします。

于 2012-04-24T11:31:04.540 に答える
2

char str[5] = "12345"-この場合、ヌルターミネータに余裕を残していません。そのため、アプリケーションが印刷を試みるとstr、nullが検出されない限り継続し、最終的には禁止されたメモリを踏んでクラッシュします。

この`cin場合、cin操作は文字列の最後に0を詰め込んだため、プログラムがメモリ内で行き過ぎないようにします。

しかし、私の経験から、メモリオーバーランでルールを破ると、物事はおかしくなり、ある場合には機能し、他の場合には機能しない理由を探しても、どこにもつながりません。多くの場合、同じアプリケーション(メモリオーバーランあり)は、異なるメモリ状態が原因で、あるPCで動作し、別のPCでクラッシュする可能性があります。

于 2012-04-24T11:31:52.970 に答える
1

コンパイラが静的チェックを行うためです。セクションIIでは、サイズは事前に不明です。入力の長さによって異なります。

STL文字列を使用することをお勧めしますか?

于 2012-04-24T11:29:28.113 に答える