在Windows(32位和64位)中,通过程序(C ++)可以确定某个内存位置是否已更改?我试图推断我们在Visual Studio中可以设置数据断点的概念。
使用案例:I understand its a dirty hack, but the fastest to implement to be re-implemented later
我跨进程边界共享数据(在32位客户端和64位服务器之间读取)。客户端分配内存(超出我们的控制范围)并将地址传递给服务器。服务器分配存储以遮蔽客户端内存,并通过各种代码路径可以更新该阴影内存位置。而不是识别和捕获每个位置(我试图找到一个更容易的路径),引发变更事件并最终通过WriteProcessMemory
将数据写回客户端进程
答案 0 :(得分:5)
虽然可能使用VirtualProtect
和Windows debug interface的组合找到解决方案,但我不确定它是否适合这种情况。其中一个问题是,您在每次新写入时都会引入延迟,并且您正在查看转移到另一个正在将程序监视为“调试器”的进程。然后,该过程必须“取消保护”该页面,将其标记为“更新”其他服务器(或客户端,具体取决于您要前往的方向),并“继续”进行更新的应用程序。这非常耗时。当然,没有什么简单的方法可以知道写作过程何时完成了一系列更新。当有SEH“__except”调用时,你还需要确切知道“继续”的位置,并且它并不总是完全无关紧要,特别是如果代码位于memcpy或类似的东西中。
当我使用图形时,我知道我们和一些竞争对手的驱动程序会这样做,首先写保护内存,然后通过挂钩到windows自己的页面错误处理程序,查找页面错误,请参阅如果它是特殊区域,如果是,则将该页面标记为已更新并将其重置为可写入。这允许驱动程序仅复制更新的区域。但在这种情况下,在完成所有更新后,有一个明显的“我想画这个东西”。
答案 1 :(得分:2)
如果你想要足够严重,可以使用调试API在你自己的数据上设置断点,这将在写入时触发,就像VS API一样。
这个的基础是启动一个线程来进行“调试”。它会:
这是从记忆开始的,所以虽然我认为它与基本想法非常接近,但我可能已经得到了一两个错误,或者(更有可能)遗漏了几个步骤。
在大多数情况下,在源级别执行某些操作会更容易,您可以为所讨论的目标重载operator=
,这样您就可以在分配数据时执行一些代码。然后在该运算符中,您可以(例如)设置一个事件,使另一个线程中的代码等待(并做出适当的反应)。
另一种可能性(特别是如果你想打破对整个地址范围的任何访问)是使用VirtualProtect
强制对该内存块的任何访问进行异常。像调试异常一样,这将同步触发,因此如果你想要异步执行,你必须通过设置一个Event(或其他)并让另一个线程等待它来完成它,这样它就会在设置Event时执行。