2

いくつかの疑問があります。メモリ内の特定の場所に変数を手動で配置することができない場所をいくつか覚えていますが、このコードに出くわしました

#include<stdio.h>
void main()
{
int *x;
x=0x200;
printf("Number is %lu",x); // Checkpoint1
scanf("%d",x);
printf("%d",*x);
}

特定の場所に置くことができないということですか、それとも、それが有効な場所かどうかわからないので、特定の場所に置くべきではないということですか?

また、このコードでは、最初のチェックポイントまで、出力が 512 になります。その後、Seg Fault.

誰かが理由を説明できますか?0x200 は有効なメモリ位置ではありませんか?

4

3 に答える 3

3

一般的なケースでは、得られる動作は定義されていません。すべてが発生する可能性があります。

たとえば Linux では、最初の 1GB がカーネル用に予約されているため、アクセスしようとすると、ユーザー モードでカーネル メモリにアクセスしようとするため、セグ フォールトが発生します。

Windowsでどのように機能するかわかりません。


Linux クレームの参照:

現在、32 ビット x86 アーキテクチャーが最も一般的なタイプのコンピューターです。このアーキテクチャでは、伝統的に Linux カーネルが 4GB の仮想メモリ アドレス空間をユーザー プログラム用の 3GB とカーネル用の 1GB に分割しています。

于 2012-10-21T20:10:26.760 に答える
0

「チェックポイント」まで、メモリ位置0x200にアクセスしていないため、すべてが正常に機能します。

x関数にローカル変数がありますmain。これは「intへのポインタ」タイプです。x値0x200が割り当てられ、その値が出力されます。ただし、xのターゲットにはアクセスされていないため、これまでxは、有効なメモリアドレスを保持しているかどうかは関係ありません。

次にscanf、渡したメモリアドレス(に格納されている0x200)に書き込もうとしますx。次に、セグメンテーション違反が発生します。これは、任意のメモリアドレスに書き込もうとした結果である可能性があります。

それで、あなたの疑問は何ですか?明らかに機能しないこのコードに出くわしたときに、これが機能する可能性があると思われる理由は何ですか?

特定のメモリアドレスへの書き込みは、特定の条件下で機能する可能性がありますが、一般的にはほとんど機能しません。最近のすべてのOSでは、通常のプログラムはメモリレイアウトを制御できません。OSは、プログラムのコード、スタック、グローバルなどの最初のものがどこに行くかを決定します。OSもおそらくある程度のメモリスペースを使用しているので、何を使用しているかを通知する必要はありません。代わりに、(変数を作成するか、メモリ割り当てルーチンを呼び出すことによって)メモリを要求し、それを使用します。

したがって、特定のアドレスに書き込むと、割り当てられていないメモリ、または他の目的で使用されているメモリが取得される可能性が非常に高くなります。実際に書き込み可能なアドレスをヒットしたとしても、どちらも適切ではありません。プログラムの他の変数の1つで使用されるデータの一部を壊してしまうとどうなりますか?または、プログラムの他の部分が、今書いた値を覆い隠しますか?

ハードコードされた特定のメモリアドレスを選択することは絶対に避けてください。変数であることがわかっているアドレス、またはなどから取得したアドレスを使用する必要がありますmalloc

于 2012-10-21T23:38:31.017 に答える
0

@amitが書いたものに追加:

Windowsでも同じです。一般に、すべてのプロテクト モード オペレーティング システムで同じです。DOS などがなくなったので、カーネルモード (km-drivers) と組み込みシステムを除くすべてのシステムで同じです。

オペレーティングシステムは、書き込みが許可されているメモリページを管理し、他のページが書き込まれた場合に CPU が自動的にアクセス違反を発生させるマーカーを配置します。

于 2012-10-21T20:15:38.617 に答える