解放されたメモリに (読み取り専用で) アクセスすると、アクセス違反が発生する可能性がありますか? また、発生する場合、どのような状況で発生しますか?
8 に答える
はい、できます。「アクセス違反」(「セグメンテーション違反」など) は、OS が「空」、「解放済み」、または他の理由でアクセスできません。ここでの重要なポイントは、OS/ハードウェアが認識しなければならないということですメモリが空いていること。C 標準ライブラリのメモリ管理関数は、「解放された」メモリを OS に返すとは限りません。彼らは将来の割り当てのためにそれを保持するかもしれません(そして保持するでしょう)。そのため、「解放された」メモリにアクセスしても「アクセス違反」にならない場合があります。これは、OS/ハードウェアの観点から、このメモリは実際には解放されていないためです。ただし、ある時点で、標準ライブラリが収集した空きメモリを OS に戻すことを決定する場合があります。その後、そのメモリにアクセスしようとすると、通常は「アクセス違反」が発生します。
あなたは「意志」ではなく「できる」と尋ねているので、あなたの答えは「はい」です。プログラムが所有していないメモリを指すことは未定義の動作であるため、何かが起こる可能性があります。
しますか?依存します。それは非常にOS固有です。あなたはそれを回避できるかもしれませんが、明らかにこれに依存することはできません. OS が独自に使用するためにメモリを再利用しているため、逆参照しようとすると例外が発生する可能性があります。(繰り返しますが、OS 固有)。
Windows の場合: Win32 での仮想メモリの管理
空き、予約済み、およびコミット済みの仮想メモリ
プロセス内のすべてのアドレスは、任意の時点で解放、予約、またはコミットされていると考えることができます。プロセスは、すべてのアドレスが解放された状態で開始されます。つまり、アドレスは解放されてメモリにコミットされたり、将来の使用のために予約されたりします。空きアドレスを使用する前に、まず予約済みまたはコミット済みとして割り当てる必要があります。 予約済みまたは空きのアドレスにアクセスしようとすると 、アクセス違反例外が生成されます。
解放されたメモリはもうあなたのものではありません。正確には、対応する物理メモリページはプロセスアドレス空間の外にあり、解放後にすでに他のプロセスアドレス空間に再マップされている可能性があり、アクセスしているそのアドレスには物理ページが割り当てられておらず、マッピングはまだです。そのため、読み取り専用でもアクセスすると「アクセス違反」や「セグメンテーション違反」が発生します。一般的に、OS ではなく GP# などのプロセッサ ハードウェアによってトリガーされます。
ただし、解放されたメモリを所有する特定の物理ページがまだタスク コンテキストの制御下にある場合、たとえばページの一部がまだプロセスによって使用されている場合、「アクセス違反」または「segfault」は発生しない可能性があります。
確かに許可されています。free
C標準では、「またはrealloc
関数の呼び出しによって割り当て解除されたスペースを参照するポインターの値が使用される」場合、動作は未定義であると率直に述べています。実際には、OS の動作方法により、クラッシュよりもガベージが発生する可能性が高くなりますが、未定義の動作を呼び出したときに何が起こるかについて、何も想定することはできません。
コードをプロファイリングし、解放されたメモリにアクセスするとパフォーマンスが大幅に向上することがわかったためにこれを尋ねている場合、解放されたブロックが小さい場合、答えはほとんどありません。確実にしたい場合は、malloc() と free() の独自の代替実装を提供してください。