[解決済み】境界外の配列にアクセスしてもエラーにならない、なぜ?
質問
C++のプログラムで、以下のように境界外の値を代入しています。
#include <iostream>
using namespace std;
int main()
{
int array[2];
array[0] = 1;
array[1] = 2;
array[3] = 3;
array[4] = 4;
cout << array[3] << endl;
cout << array[4] << endl;
return 0;
}
プログラムは次のように表示します。
3
と
4
. ありえないはずです。 私はg++ 4.3.3を使っています。
以下はコンパイルと実行のコマンドです。
$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4
を割り当てる場合のみ
array[3000]=3000
を実行すると、segmentation fault が発生します。
gccが配列の境界をチェックしない場合、私のプログラムが正しいかどうか、後で深刻な問題につながる可能性があるので、どうしたら確認できますか?
上記のコードを
vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout << vint[5] << endl;
で、こちらもエラーは出ません。
解決方法は?
C/C++プログラマの最良の友へようこそ。 未定義の動作 .
さまざまな理由から、言語規格で規定されていないことがたくさんあります。これもそのひとつです。
一般に、未定義の動作に遭遇したときはいつでも 何でも が起こるかもしれません。アプリケーションがクラッシュしたり、フリーズしたり、CD-ROMドライブが取り出されたり、鼻から悪魔が出たりするかもしれません。ハードディスクをフォーマットしたり、おばあちゃんにポルノを全部メールで送ったりするかもしれません。
本当に運が悪いと、こんなこともあるかもしれません。 現れる は正しく動作します。
この言語は単純に、以下の要素にアクセスした場合に何が起こるべきかを述べています。 内の 配列の境界。境界からはみ出したらどうなるかは未定義です。もしかしたら と思われる しかし、これは合法的なCやC++ではありませんし、次にそのプログラムを実行したときにまだ動くという保証はありません。あるいは、現在でも必要なデータが上書きされておらず、問題に遭遇していないだけで、そのプログラムが は を引き起こします。
については なぜ を使用した場合、境界チェックが行われないため、その答えにはいくつかの側面があります。
- 配列はC言語の名残で、C言語の配列は原始的と言えるでしょう。連続したアドレスを持つ要素の列です。単に生のメモリを公開しているだけなので、境界チェックはありません。堅牢な境界チェック機構を実装することは、C言語ではほとんど不可能だったでしょう。
- C++では、クラス型に対して境界チェックが可能です。しかし、配列はまだC互換のプレーンなものだ。クラスではありません。さらに、C++は、境界チェックを非理想的なものにする別のルールの上に成り立っている。C++の指針は、"you don't pay for what you don't use"(使わないものにはお金を払わない)だ。コードが正しければ、境界チェックは必要ありませんし、実行時の境界チェックのオーバーヘッドにお金を払うことを強制されるべきでもありません。
-
そこでC++では
std::vector
クラスのテンプレートで、両方を可能にします。operator[]
は効率的であるように設計されています。言語規格では、境界チェックを行うことは要求されていない(禁止もされていない)。また,ベクトルにはat()
メンバー関数 が保証されている で境界チェックが行われます。つまり、C++では、ベクターを使えば、両方の長所を得ることができるのです。C++では、ベクトルを使えば、境界チェックをせずに配列のようなパフォーマンスを得ることができます。 と 必要なときに境界チェックされたアクセスを使用することができます。
関連
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み] 配列の反復処理に "for...in "を使用するのは、なぜ良くないのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】coutはstdのメンバではない
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】Enterキーを押して続行する
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] 配列のベクトルを扱う正しい方法
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む