5

さて、私はガールフレンドにc ++を教えていました。彼女は私がうまくいかないと思ったプログラムを書きましたが、うまくいきました。配列内のもう1つの要素にアクセスし、次に存在します(たとえば、サイズ5の配列の場合はarray [5]にアクセスします)。これはバッファオーバーフローのインスタンスですか?私の考えでは、配列の直後にメモリへの書き込み/メモリへのアクセスを行っていますが、これは正しいですか?基本的にここでの私の質問は..なぜこれが機能するのですか?

#include <iostream>

using namespace std;

int main()
{
int size;

cout << "Please enter a size for the array." << endl;
cin >> size;
cout << endl;

cout << "There are " << size << " elements in this array." << endl;
cout << endl;
cout << endl;
cout << endl;

int array[size];

for (int counter = 1; counter <= size; counter++)

{
    cout << "Please enter a value for element " << counter << "." << endl;
    cin >> array[counter];

}

cout << endl;
cout << endl;


for (int counter = 1; counter <= size; counter++)

{
    cout << "Element " << counter << " is " << array[counter] << "." << endl;
    cout << endl;

}

cout << "*bing! :)" << endl;
cout << endl;


return 0;
}
4

5 に答える 5

22

未定義の動作です。UB にはさまざまな種類があります。ここにいくつかあります:

1) それはあなたの犬を蹴ります。

2) ハード ドライブが再フォーマットされます。

3) 問題なく動作します。

あなたの場合、コンパイラとプラットフォームで、この特定の日に、(3) が表示されます。しかし、別の場所で試してみると、(1)、(2)、またはまったく別の結果になる可能性があります (アクセス違反の可能性が最も高い)。

于 2012-04-07T04:39:24.707 に答える
6

配列を使用する場合、C/C++ は境界チェックを行いません。

スタックベースの配列を宣言しているため。配列の境界外にアクセスすると、既に割り当てられているスタック領域の別の部分にアクセスするだけです。

したがって、基本的に、範囲外のものにアクセスしても、スタック メモリが完全に不足していない限り、セグメンテーション フォールトは発生しません。

C/C++ は配列境界で危険であることを覚えておいてください!

于 2012-04-07T04:40:52.860 に答える
2

スタックは非常に大きいです。Windows では1 MBです。

プログラムは多くのことを行わないため、配列はスタックの先頭近くに割り当てられます。これは、配列の最後とスタックの最後の間にほぼ 1 MB の空きスペースがあることを意味します。

では、これはどういう意味ですか?配列の末尾を超えて書き込むと、他のプログラムではなく、自分のスタック領域を破壊するだけなので、OS は停止せず、プログラムは実行を続けます。

于 2012-04-07T05:11:24.877 に答える
0

まず、配列サイズは一定である必要があるため、

 int arr[size] 

サイズは変数であるため機能しません。したがって、コンパイル時に配列のサイズを修正するか、動的メモリ割り当てを使用してください。

すなわちどちらか

  const int size =5; 
  int arr[size];

また

  int arr[5];

また

  int* arr = new int[5];

と..

配列の終わりを超えて1つの要素へのポインターを取ることは、C++で機能することが保証されています。これは、STLによって提供される多くのアルゴリズムにとって重要です。ただし、このようなポインタは実際にはarayの要素を指していないため、読み取りと書き込みには使用できません。一方、最初の要素の前に要素のアドレスを取得した結果は未定義であり、回避する必要があります。

つまり、その変数のアドレスを取得してから戻ってくることはできますが、使用することはできません!!!

于 2012-04-07T04:46:27.677 に答える
0

ここで、配列インデックスが 0 から始まり、5 に移動することがわかります

カウンターを 5 として入力します。これは 1 から始まり、5 に進みます

カウンター 1 にはインデックス 1、カウンター 2 にはインデックス 2 などを使用しています。

インデックス 0 にはまだ入力値がなく、ガベージ値が含まれています。

于 2012-04-07T04:51:14.827 に答える