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