1
#include <iostream>
using namespace std;

int a[4];
int main(){
    int b=7;
    cout<<a[b]<<endl;
    return 0;
}

割り当てられていないメモリにアクセスしようとしていました。したがって、出力はセグメンテーション違反であると予想されますが、出力はガベージ値です。

後で 'b' を 1000 に増やしたところ、出力は 'Segmentation fault' になりました。この種の行動には特定の理由がありますか?

gcc-4.3.2 コンパイラを使用しています。

4

5 に答える 5

2

セグメンテーション違反は、オペレーティング システムがアクセスを許可していないメモリにアクセスした場合にのみ発生します。

ただし、期待したものとは異なりますが、許可されているメモリ (たとえば、スタック内の前後を指しているメモリ アドレス) にアクセスすることはできます。しかし、ローカルに保存された変数がスタックに配置される方法は、デバッグからリリース、コードの変更など、さまざまな難解な最適化に従ってコンパイラによって決定されるため、一貫性に依存できるものではありません。

しかし、「なぜこの変数にアクセスするとガベージが発生するのに、常に同じガベージが返されるのですか?」のようなものを見たことがあれば、おそらく、意図せずにスタックの覗いてはならない部分を覗いています。

于 2013-04-08T04:45:20.763 に答える
1

これは未定義の動作であるため、何が起こるかわかりません。これをチェックして (C++ の場合)、未定義の動作、未指定の動作、および実装定義の動作の違いを確認してください。

C -**ISO C9899**附属書 J では、これについて明確に述べています。

EDIT
C++ -N3485 ISO/IECセクション1.9.2では1.9.31.9.4上記の動作について説明しています。

于 2013-04-08T04:45:32.173 に答える
0

範囲外アクセスは未定義の動作です。プロセス空間の任意のメモリにアクセスできます。アクセスされたメモリが割り当てられていないか、プロセスのアドレス空間にない場合 (カーネルにある可能性があります)、プログラムはセグメンテーション違反でクラッシュします。このような場合、障害は問題を特定するのに役立ちます。運が良ければクラッシュが発生する可能性があり、そうでない場合は気付かれず、後で追跡が困難なメモリを破損するプログラムでバグが発生する可能性があります。[1000] が割り当てられない確率が高くなるため、クラッシュが発生します。メモリはページ単位で割り当てられます。

于 2013-04-08T04:45:13.510 に答える
0

セグメンテーション違反を引き起こすために、未定義の動作は必要ありません。int i = INT_MAX + 1;一般にセグメンテーション違反を引き起こさない未定義の動作の別の例を考えてみましょう。

于 2013-04-08T05:06:04.100 に答える