5

ヒープの破損をデバッグするための手法を概説したこの興味深い記事を読んだ後、自分のニーズに合わせてそれをどのように調整できるのか疑問に思い始めました。基本的な考え方は、メモリのページ全体を割り当てるためのカスタムmalloc()を提供し、それらのページのメモリ保護ビットを有効にして、書き込み時にプログラムがクラッシュし、問題のある書き込み命令が動作に巻き込まれるようにすることです。 。サンプルコードはLinuxではC(mprotect()は保護を有効にするために使用されます)であり、これをネイティブC++およびWindowsに適用する方法について興味があります。VirtualAlloc()やVirtualProtect()は有望に見えますが、使用シナリオがどのようになるかはわかりません。

Fred *p = new Fred[100];
ProtectBuffer(p);
p[10] = Fred(); // like this to crash please

Windowsのメモリ破損をデバッグするための専用ツールの存在を認識していますが、このアプローチを使用して「手動で」それを実行できるかどうかはまだ興味があります。

編集:また、これはWindowsでの良いアイデアですか、それとも単なる面白い知的演習ですか?

4

2 に答える 2

4

はい、VirtualAllocとVirtualProtectを使用して、読み取り/書き込み操作から保護されるメモリのセクションを設定できます。

operator newメモリ割り当てがコードによって制御されるように、およびoperator delete (およびそれらの[]親戚)を再実装する必要があります。

また、ページごとにのみ使用され、割り当てごとに(少なくとも)3ページ分の仮想メモリを使用することに注意してください。64ビットシステムでは大きな問題ではありませんが、次の場合に問題が発生する可能性があります。 32ビットシステムには多くの割り当てがあります。

大まかにあなたがする必要があること(あなたは実際にWindowsのビルドのためのページサイズを見つけるべきです-私はあまりにも怠惰なので、ページサイズとページサイズ-1を表すために4096と4095を使用します-あなたももっとする必要がありますこのコードよりもエラーチェック!!!):

void *operator new(size_t size)
{
    Round size up to size in pages + 2 pages extra.
    size_t bigsize = (size + 2*4096 + 4095) & ~4095; 

    // Make a reservation of "size" bytes. 
    void *addr = VirtualAlloc(NULL, bigsize, PAGE_NOACCESS, MEM_RESERVE);

    addr = reinterpret_cast<void *>(reinterpret_cast<char *>(addr) + 4096);

    void *new_addr = VirtualAlloc(addr, size, PAGE_READWRITE, MEM_COMMIT); 

    return new_addr;
}

void operator delete(void *ptr)
{
    char *tmp = reinterpret_cast<char *>(ptr) - 4096;

    VirtualFree(reinterpret_cast<void*>(tmp)); 
}

私が言ったように、これらの線に沿った何か-私はWindows VMしか持っていないので、このコードをコンパイルしようとはしていません。コンパイラをダウンロードして実際にコンパイルされるかどうかを確認するのは面倒です。[私は数年前に働いていたのと同じようなことをしたので、原則が機能することを知っています]。

于 2013-01-30T03:28:43.180 に答える
2

これがGaurdPagesの目的です(このMSDNチュートリアルを参照)。ページに最初にアクセスしたときに特別な例外が発生し、最初の無効なページアクセスでクラッシュする以上のことができます(対照的に、不正な読み取り/書き込みをキャッチできます) NULLポインタなどへ)。

于 2013-01-30T14:39:04.800 に答える