我一直认为这是Visual Studio中非常有用的功能.对于那些不了解它的人,它允许您在调试正在运行的进程时编辑代码,在二进制文件仍在运行时重新编译代码并继续使用应用程序与新代码无缝地使用,而无需重启它.
这个功能是如何实现的?如果我修改的代码在应用程序加载的DLL中,应用程序是否只是卸载DLL并重新加载它?在我看来,这似乎很容易出现不稳定问题,所以我认为它会比这更聪明.有任何想法吗?
我的理解是,当编译应用程序并支持编辑和继续启用时,编译器会在二进制映像中的函数周围留出额外的空间,以允许添加其他代码.然后调试器可以编译该函数的新版本,替换现有版本(根据需要使用填充空间),修复堆栈,设置指令指针,然后继续.这样你就不必修改任何跳转指针,只要你有足够的填充.
请注意,编辑和继续通常不适用于libs/dll中的代码,只能使用主可执行代码.
我的猜测是它重新编译应用程序(对于小的更改,这并不意味着必须重新编译).然后,由于Microsoft同时生成编译器和调试器,因此可以保证如何布局内存等.因此,只要更改足够小,他们就可以使用调试API重新编写具有新代码段的代码段.
如果更改重定向到全新的代码,显然可以以与DLL类似的方式将其加载到内存中.
微软还有一个"热补丁"机制.函数在任何实际代码之前都有一个2字节的无操作指令,通常类似于"mov edx,edx".这允许他们干净地重定向函数的执行.这也可能是一种选择.
要记住的关键是应用程序没有"运行",它的所有线程都处于停止状态.因此,就过程而言,调试器所做的任何修改都是完全原子的.
当然,这都是猜测;)