0

任意のアドレスに値を割り当てているため、次のコードが正しくないことがわかります。

#include <iostream>

using namespace std;

int main()
{
int *i;
*i = 12;     // Not right.... i is not initialized.
cout << *i << endl;
return 0;
}

このコードは、Linuxでセグメンテーション違反を引き起こします。ただし、Windowsでは12を出力します...

なぜそれはWindowsで動作するのでしょうか?プログラムに特権がない任意の場所に12を割り当てていませんか?

4

3 に答える 3

12

実際には未定義の動作を呼び出します。したがって、両方の動作が正しいです。つまり、セグメンテーション違反が発生する場合と発生しない場合があります。

次回の実行時に、Windowsバージョンがクラッシュし、Linuxバージョンから脅迫メールが送信される可能性があります。

言い換えれば、何でも起こり得るのです。C ++仕様も(標準準拠の)コンパイラも保証を提供しません。そのため、C++仕様は未定義動作などの動作を参照します。

于 2012-06-07T17:11:09.630 に答える
2

たまたまiスタックに置かれた場所にあるランダムデータは、Linux ではたまたま書き込み不可のアドレスを形成しますが、Windows ではたまたま書き込み可能なアドレスを含んでいるためです。

ただし、コードが Windows に与えるその他の影響を確実に知ることはできないことに注意してください。たまたま 13 日の金曜日の午後 6 時 16 分にプログラムを開始した場合、そのアドレスはたまたま出力」のシステム コール番号が保存されているアドレスである可能12あります。 「ファイルを削除」すると、最も重要なファイルが削除される場合がありますはい、非常にありそうにありませんが、まったく不可能ではありません (特定のコンパイラ設定を使用して、特定のコンパイラの特定のバージョンでコンパイルした場合にのみ発生する可能性があります)。

つまり、このコードを実行するとどうなるかは誰にもわかりません (Linux でも、コンパイラ オプションやコンパイラのバージョンを変更したり、たまたまコマンド ライン引数で呼び出したりすると、動作が異なる可能性があることに注意してください ... )

于 2012-06-07T17:22:20.070 に答える
1

@Nawazと@celtschkは正しいです。あなたのコードは未定義の動作を呼び出すので、どちらの動作も正しいです。それでも、この特定の未定義の動作が見られるのには理由があります。その理由は理解する価値があります。

オペレーティング システムが実行時にプログラムをロードすると、仮想アドレス空間が開かれます。 64 ビット システムでは、仮想空間はアドレス 0 からアドレス 0xffffffffffffffff まで拡張されます。

あなたのシステムは当然、そのような広大なアドレス空間を満たすために必要な実際の物理メモリのほんの一部しか持っていません. さらに、システムは、一度に実行される可能性のあるいくつかの異なるプロセス間でメモリを共有する必要があります。各プロセスには、独自のプライベート仮想アドレス空間があります。

システムの機能は次のとおりです。最初に、新しくロードされたプログラムに小さなメモリ ブロック (おそらく 4 kiB) を割り当て、これをアドレス空間の小さなセグメント (0xffffffffffffff000 ~ 0xffffffffffffffff) にマップします。プログラムは、このスペースに格納されたデータ オブジェクトのスタックを構築します。スタックが 4 kiB を超えて大きくなると、システムは別の 4 kiB を 0xffffffffffffe000 から 0xffffffffffffefff として割り当て、実行中のプログラムに対して透過的な方法でそれを行います。

プログラムが規則正しく規定された方法でスタックを構築して使用する限り、スタックのサイズの制限を認識していないかのように実行されます。ただし、プログラムが無秩序な方法でメモリにアクセスすると、結果はいくつかの要因に依存しますが、システムがプログラムの実際のメモリを割り当てたことのないアドレスへのアクセスである場合、システム例外が確実に発生します。使用する。

さて、この回答では多くの詳細が省略されています。ご存知かもしれませんが、ヒープまたは動的メモリ プールという 2 番目の種類のメモリがあります。 「ディスクの交換」など、他にも要因があります。ただし、ポインターiがたまたまプログラムが何らかの目的で既に使用しているメモリを指している場合、システム例外は発生しません。それはそのような記憶を指していますか?言いにくい。明らかに、あなたの場合、あるシステムではそうしているようですが、他のシステムではそうではないようです。

ちなみに、@celtschk とは 1 つの小さな点で少し異なります。最新の CPU とオペレーティング システムは、彼が話しているようなシステム障害を防ぐように特別に構築されています。C および C++ 標準は、このような障害が発生しないことを保証していませんが、プログラムがスーパーユーザー特権で実行されない限り、オペレーティング システムは発生します (また、部分的に有効な保護手段が存在する場合でも)。通常のユーザーモード プログラムで不注意にディスクを消去してしまうことについて、あまり心配する必要はないと思います。それでも、組み込みシステムでは、それは別の問題であり、@celtschk はまったく正しいです。

于 2012-06-07T17:31:46.527 に答える