For the sake of completeness, here's version of memory debugger for Win32.
It uses vectored exception, so works only for Win2K or later.
#define_WIN32_WINNT 0x0500 #include<stdio.h> #include<windows.h> #include<process.h> #include<stdlib.h> #include<float.h>typedefenum { BREAK_ON_EXEC = 0x00, BREAK_ON_WRITE = 0x01, BREAK_ON_RW = 0x03, } BreakFlags;typedefenum { LEN_1 = 0x00, LEN_2 = 0x01, LEN_4 = 0x03, } DataLength;typedefstruct {int dr0_local:1;int dr0_global:1;int dr1_local:1;int dr1_global:1;int dr2_local:1;int dr2_global:1;int dr3_local:1;int dr3_global:1;int exact_local:1;int exact_global:1;int reserved:6; BreakFlags dr0_break:2; DataLength dr0_len:2; BreakFlags dr1_break:2; DataLength dr1_len:2; BreakFlags dr2_break:2; DataLength dr2_len:2; BreakFlags dr3_break:2; DataLength dr3_len:2; } DR7;typedefstruct {void* addr; HANDLE tid; PVECTORED_EXCEPTION_HANDLER handler; } params_t;voidrunner(void* pv) { CONTEXT ctx; params_t* p = (params_t*)pv; DWORD rv; SuspendThread(p->tid); DR7 dr7 = {0}; dr7.dr0_local = 1; dr7.dr0_break = BREAK_ON_WRITE; dr7.dr0_len = LEN_4; ctx.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; GetThreadContext(p->tid, &ctx); ctx.Dr0 = (DWORD)(intptr_t)p->addr; ctx.Dr6 = 0; ctx.Dr7 = *(DWORD*)&dr7; SetThreadContext(p->tid, &ctx); AddVectoredExceptionHandler(1, p->handler); ResumeThread(p->tid); }voidaddwatchpoint(HANDLE tid, void* address, PVECTORED_EXCEPTION_HANDLER handler) { params_t p = { address, tid, handler }; HANDLE setter = (HANDLE)_beginthread(runner, 1024*1024, &p); WaitForSingleObject(setter, -1); }volatileint var = 0; LONG WINAPI trap(PEXCEPTION_POINTERS ExceptionInfo) {if (var == 50) { printf("caught: %d\n", var);while (1) {} }return EXCEPTION_CONTINUE_EXECUTION; }intmain(int argc, char* argv[]) {int i; HANDLE me = OpenThread(THREAD_ALL_ACCESS, false, GetCurrentThreadId()); addwatchpoint(me, (void*)&var, &trap);for (i=0; i<100; i++) { var++; } getchar();return 0; }