無効なメモリへのアクセスがセグメンテーション違反を引き起こし、システムがクラッシュする可能性があることがわかっています。システムがクラッシュする前に、メモリが無効かどうかを知りたいです。
4 に答える
これは Linux 固有のものですが、実装が簡単で信頼性があります。
開く/proc/self/maps
。これは、現在のプロセスのすべてのメモリ マップを一覧表示するテキスト疑似ファイルです。man 5 procで説明されています。セクションを参照してください/proc/[pid]/maps
。線は次のようになります
7fb5cb179000-7fb5cb32e000 r-xp 00000000 fc:00 14651 /lib/x86_64-linux-gnu/libc-2.15.so
-
ただし、ダッシュまでの 16 進数の開始アドレス、スペースまでの 16 進数の終了アドレス (包括的ではなく、マップのすぐ外側の最初のアドレス) 、および次のスペースまでのいくつかのモード文字のみを解析する必要があります
。
モード文字r
は、マッピングが読み取り可能、w
書き込み可能、x
実行可能、s
共有、およびp
プライベートであることを意味します。(将来的には他の文字もあるかもしれないので、それらとスペース以外はすべて無視するのが最善です。)
long
は C で最大の標準整数型であるため、アドレス (解析時を含む) に使用する必要がありunsigned long
ます。を使用して、任意のポインターをアドレスに変換することもできます(unsigned long)pointer
。を使用int
すると、ほとんどの 64 ビット Linux アーキテクチャでは機能しません。32 ビットになる傾向があるため、すべてのポインターを表すことができません。
ポインター アドレスがこれらすべてのマップの外側にある場合、無効であることが保証されます。ポインターを逆参照すると、セグメンテーション フォールトが発生します。
ポインターが上記のマップのいずれかにある場合、マップのモードは、有効な操作とそのマップの種類を示します。ポインターがデータを指すことを意図していることがわかっている場合は、たとえば、ターゲット マップが実行可能であってはならないことがわかります。
マルチスレッド プログラムでは、メモリ マップの一貫したスナップショットが表示されるように、一度にファイル全体をメモリに読み込んでから、文字列操作を使用してデータを解析する必要があります。ファイル全体を読み取っていないことがわかった場合は、ファイルを再度読み取ってください。これを行うには、(またはunistd.h
の関数を使用する代わりに)からの低レベル I/Oを使用して、キャッシュと抽象化を回避する必要があります。実際、シングルスレッド アプリケーションにもこの手順をお勧めします。これは堅牢なアプローチです。stdio.h
mman.h
短い答えは、これを行うための移植可能で信頼できる方法がないということです。
これは 100% 正しく、あるべき姿です。あなたが求めているのは、「プログラムにバグがあることをプログラムに検出させるにはどうすればよいですか?」ということです。- 無効なポインターを取得できる唯一の方法は、バグがある場合 (または単純に不適切に記述されたコード) の場合です。
valgrind などを使用してコードを分析し、不正なメモリ アクセスを引き起こすバグを修正するというアイデアが最善の解決策です。
興味深いトピック。こちらの議論をご覧ください: http://www.cplusplus.com/forum/beginner/49550/
Microsoft は、この目的のために次の関数を提供しました: IsBadReadPtr ( http://msdn.microsoft.com/en-us/library/aa366781(VS.85).aspx )
Linux のようなものは見つかりませんでした。ただし、valgrind ( http://valgrind.org/ )でプログラムを実行して、無効なポインター参照を検出できます。
最新のマルチユーザー オペレーティング システムでは、無効なメモリ アクセスによってシステムがクラッシュすることはありません。無効なアクセスを行ったプログラムのみがクラッシュします。