【问题标题】:How does "Edit and continue" work in Visual Studio?Visual Studio 中的“编辑并继续”如何工作?
【发布时间】:2010-09-18 11:29:18
【问题描述】:

我一直发现这是 Visual Studio 中一个非常有用的功能。对于那些不了解它的人,它允许您在调试正在运行的进程时编辑代码,在二进制文件仍在运行时重新编译代码,并继续无缝地使用应用程序与新代码,无需重新启动。

这个功能是如何实现的?如果我正在修改的代码在应用程序加载的 DLL 中,应用程序是否只是卸载 DLL 并重新加载它?在我看来,这似乎很容易出现不稳定问题,所以我认为它会比这更聪明。有什么想法吗?

【问题讨论】:

    标签: c++ visual-studio


    【解决方案1】:

    我的理解是,当应用程序在启用编辑并继续支持的情况下编译时,编译器会在二进制映像中的函数周围留出额外的空间,以允许添加额外的代码。然后调试器可以编译新版本的函数,替换现有版本(根据需要使用填充空间),修复堆栈,设置指令指针,然后继续。这样一来,您就不必修复任何跳转指针,只要您有足够的填充。

    请注意,“编辑并继续”通常不适用于 libs/dll 中的代码,只能用于主要的可执行代码。

    【讨论】:

      【解决方案2】:

      我的猜测是它会重新编译应用程序(对于小的更改,这并不意味着必须重新编译太多)。然后,由于 Microsoft 制造了编译器和调试器,因此他们可以保证内存等的布局方式。因此,只要更改足够小,他们就可以使用调试 API 用新的代码段重写代码段。

      如果更改重定向到全新的代码,这显然可以以与 DLL 类似的方式加载到内存中。

      Microsoft 还有一种“热补丁”机制。函数在任何实际代码之前都有一个 2 字节的无操作指令,通常类似于“mov edx,edx”。这允许他们干净地重定向函数的执行。这也可能是一种选择。

      要记住的关键是应用程序没有“运行”,它的所有线程都处于停止状态。因此,就进程而言,调试器所做的任何修改都是完全原子的。

      当然,这都是猜测;)

      【讨论】:

      • 我喜欢将函数执行重新路由到外部位置的想法。当我用“/ZI”构建exe时,我在可执行文件中看到一个新的部分“.textbss”,可能是用来存储编辑过的代码。
      • 根据dumpbin的说法,“.textbss”部分被标记为未初始化,并且具有读+写+执行权限,非常适合存储和执行动态生成的代码=)
      【解决方案3】:

      我的猜测是所有对象都与 4096 字节的内存边界对齐。因此,如果您对某些代码进行小的更改,那么对象仍将在这些边界内,因此会像以前一样运行。

      我曾遇到过更改几行将导致完全重新编译和链接的情况,而在其他情况下,对函数进行相当大的重构就可以了。

      【讨论】:

      • 使用 ollydbg 之类的调试器查看代码表明它们未与页面边界对齐。但是,可能会添加一些填充(一点)以使更大尺寸的更改成为可能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      相关资源
      最近更新 更多