mprotect hat einen Nachteil: Ihr Speicher muss Seitenrand ausgerichtet sein. Ich hatte mein problematisches Gedächtnis auf dem Stapel und konnte mprotect() nicht benutzen.
Wie Adam sagte, was Sie wollen, ist die Debug-Register zu manipulieren. Unter Windows habe ich das benutzt: http://www.morearty.com/code/breakpoint/ und es hat super funktioniert. Ich habe es auch auf Mach-O (Mac OS X) portiert, und es hat auch super funktioniert. Es war auch einfach, weil Mach-O thread_set_state() hat, was SetThreadContext() entspricht.
Das Problem mit Linux ist, dass es solche Äquivalente nicht hat. Ich habe ptrace gefunden, aber ich dachte, das kann nicht sein, da muss etwas einfacher sein. Aber da ist es nicht. Noch. Ich denke, dass sie an einer hw_breakpoint API für Kernel und Benutzerraum arbeiten.(siehe http://lwn.net/Articles/317153/)
Aber als ich das gefunden: http://blogs.oracle.com/nike/entry/memory_debugger_for_linux Ich habe es versucht und es war nicht so schlimm. Die ptrace-Methode arbeitet mit einem "externen Prozess", der als "Debugger" fungiert, der an Ihr Programm angehängt wird, neue Werte für die Debug-Register eingibt und mit Ihrem Programm endet, das mit einem neuen hw-Breakpoint-Satz fortfährt. Die Sache ist, Sie können diesen "externen Prozess" selbst erstellen, indem Sie fork() verwenden (ich hatte keinen Erfolg mit einem Pthread), und diese einfachen Schritte inline in Ihrem Code ausführen.
Der addwatchpoint-Code muss angepasst werden, um mit 64-Bit-Linux zu arbeiten, aber das ändert nur USER_DR7 usw. zu offsetof (struct user, u_debugreg [7]). Eine andere Sache ist, dass Sie nach einem PTRACE_ATTACH warten müssen, bis das Debuggee tatsächlich stoppt. Aber anstatt einen POKEUSER in einer geschäftigen Schleife zu wiederholen, ist das richtige was zu tun ein waitpid() auf Ihrem Pid.
Der einzige Haken mit der Ptrace-Methode ist, dass Ihr Programm nur einen "Debugger" gleichzeitig angeschlossen haben kann. Ein Ptrace-Attach wird also fehlschlagen, wenn Ihr Programm bereits unter gdb-Kontrolle läuft. Aber genauso wie der Beispielcode, können Sie einen Signalhandler für SIGTRAP registrieren, ohne gdb laufen, und wenn Sie das Signal abfangen, geben Sie eine Busy-Schleife ein, die auf gdb zum Anhängen wartet. Von dort können Sie sehen, wer versucht hat, Ihre Erinnerung zu schreiben.
Auf die Debug-Register kann nur auf Berechtigungsstufe 0 zugegriffen werden, d. H. Im Kernel. Siehe http://pdos.csail.mit.edu/6.828/2008/readings/i386/s12_02.htm –