受支持的代码更改 (C++)

C++ 项目的“编辑并继续”可处理大多数类型的代码更改。 但是,在程序执行期间,某些更改无法应用。 若要应用这些更改,您必须停止执行并生成新版本的代码。

有关在 Visual Studio 中使用 C++ 的“编辑并继续”的信息,请参阅编辑并继续 (C++)

要求

生成设置(项目 > 属性):

  1. C/C++ > 常规 > 调试信息格式:用于“编辑并继续”的程序数据库 (/ZI)

  2. 链接器 > 常规 > 启用增量链接:是 (/INCREMENTAL)

    在生成期间,任何不兼容的链接器设置(例如 /SAFESEH/OPT:...)都应引发警告 LNK4075 。
    示例:LINK : warning LNK4075: ignoring '/INCREMENTAL' due to '/OPT:ICF' specification

调试器设置(调试 > 选项 > 常规):

  • 启用本机“编辑并继续”

    在“编辑并继续”期间,任何不兼容的编译器或链接器设置都会引发错误。
    示例:Edit and Continue : error : ‘file.cpp’ in ‘MyApp.exe’ was not compiled with Edit and Continue enabled. Ensure that the file is compiled with the Program Database for Edit and Continue (/ZI) option.

不支持的更改

在调试会话期间,不能应用下列 C/C++ 更改。 如果进行了下列任何更改,然后尝试应用代码更改,“输出” 窗口中将显示错误或警告消息。

  • 对全局或静态数据的大多数更改。

  • 对从其他计算机复制并且未在本地生成的可执行文件的更改。

  • 对影响对象(如类的数据成员)的布局的数据类型的更改。

  • 添加 64k 字节以上的新代码或数据。

  • 添加要求在指令指针前存在构造函数的变量。

  • 影响需要运行时初始化的代码的更改。

  • 在某些实例中,添加异常处理程序。

  • 对资源文件的更改。

  • 对只读文件中的代码的更改。

  • 对没有相应的 PDB 文件的代码的更改。

  • 对没有对象文件的代码的更改。

  • 修改符合以下条件的 lambda:
    • 具有静态或全局成员。
    • 传递给 std::function。 这会导致真正的 ODR 违规并引发 C1092。
  • “编辑并继续”不更新静态库。 如果您更改了静态库,则会继续执行老版本,且不发出任何警告。

不支持的方案

在以下调试方案中,C/C++ 的“编辑并继续”不可用:

  • 调试使用 /Zo(增强优化调试)编译的本机应用

  • 使用 VC 120 工具集和 C/C++ /bigobj 开关的项目。 仅在 VC 140 工具集中支持使用 /bigobj 进行“编辑并继续”。

  • 混合模式(本机/托管)调试。

  • JavaScript 调试。

  • SQL 调试。

  • 调试转储文件。

  • 在未选择 “在未经处理的异常上展开调用堆栈” 选项的情况下,在发生未经处理的异常之后编辑代码。

  • 使用 连接到 来调试应用程序,而不是选择 调试 菜单上的 开始 来运行应用程序。

  • 调试优化后的代码。

  • 如果由于生成错误无法生成新版本的代码,则对旧版本的代码进行调试。

  • 使用自定义编译器 (cl.exe ) 路径。 出于安全原因,在“编辑并继续”期间重新编译文件时,Visual Studio 始终使用已安装的编译器。 如果使用自定义编译器路径(例如,通过 *.props 文件中的自定义 $(ExecutablePath) 变量),系统会显示一条警告,并且 Visual Studio 会回退为使用已安装的相同版本/体系结构的编译器。

  • 旧版体系结构/VC 工具集。 借助 VC 140 工具集,默认调试器支持在 X86 和 X64 应用程序中使用“编辑并继续”。 旧版工具集仅支持 X86 应用程序。 早于 VC 120 的工具集应使用旧版调试器(方法是选中“调试 > 选项 > 常规 > 使用本机兼容性模式”),才能使用“编辑并继续”。

链接限制

禁用“编辑并继续”的链接器选项

下列链接器选项可禁用“编辑并继续”:

  • 设置 /OPT:REF/OPT:ICF/INCREMENTAL:NO 将禁用“编辑并继续”并发出以下警告:
    LINK : warning LNK4075: ignoring /EDITANDCONTINUE due to /OPT specification

  • 设置“/ORDER”、“/RELEASE”或“/FORCE”将禁用“编辑并继续”并发出以下警告 :
    LINK : warning LNK4075: ignoring /INCREMENTAL due to /option specification

  • 设置任何禁止创建程序数据库 (.pdb) 文件的选项都会禁用“编辑并继续”,但不给出任何特定警告。

自动重新链接限制

默认情况下,“编辑并继续”在调试会话结束时重新链接到程序,以创建最新的可执行文件。

如果正在从原始生成位置以外的位置调试,“编辑并继续”不能重新链接程序。 有消息通知您需要手动重新生成。

“编辑并继续”不重新生成静态库。 如果使用“编辑并继续”更改静态库,需要使用“编辑并继续”手动重新生成库并重新链接应用程序。

“编辑并继续”不调用自定义生成步骤。 如果程序使用自定义生成步骤,则可能要手动重新生成这些步骤才能调用它们。 在这种情况下,可以在“编辑并继续”后禁用重新链接,以确保系统会提示您手动重新生成。

在“编辑并继续”之后禁用重新链接

  1. “调试” 菜单上,选择 “选项和设置”

  2. 选项 对话框中,在 调试 节点下,选择 编辑并继续 节点。

  3. 清除 “调试后重新链接代码更改” 复选框。

预编译头限制

默认情况下,“编辑并继续”在后台加载并处理预编译头,以加速对代码更改的处理。 加载预编译头需要分配物理内存,如果您正在一台 RAM 有限的计算机上进行编译,这可能会是一个问题。 在调试时,您可以使用 Windows 任务管理器来确定可用的物理内存量,以确定这是否可能有问题。 如果此数量大于预编译头的大小,则“编辑并继续”应没有问题。 如果此数量小于预编译头的大小,可以禁止“编辑并继续”在后台加载预编译头。

对“编辑并继续”禁用预编译头的后台加载

  1. “调试” 菜单上,选择 “选项和设置”

  2. 选项 对话框中,在 调试 节点下,选择 编辑并继续 节点。

  3. 清除 “允许预编译” 复选框。

IDL 属性限制

“编辑并继续”不重新生成接口定义语言 (IDL) 文件。 因此,调试时不反映对 IDL 特性的更改。 若要查看对 IDL 特性更改的结果,必须停止调试并重新生成应用程序。 如果 IDL 特性已更改,“编辑并继续”不生成错误或警告。 有关更多信息,请参见 IDL 特性

诊断问题

如果你的情况与上述情况均不相符,则可以通过设置以下 DWORD 注册表值来收集更多详细信息:

  1. 打开“开发人员命令提示”。
  2. 运行下面的命令:
    VsRegEdit.exe set “C:\Program Files\Microsoft Visual Studio\[Version]\[YOUR EDITION]” HKCU Debugger NativeEncDiagnosticLoggingLevel DWORD 1
    VsRegEdit.exe set “C:\Program Files (x86)\Microsoft Visual Studio\[Version]\[YOUR EDITION]” HKCU Debugger NativeEncDiagnosticLoggingLevel DWORD 1

在调试会话开始时设置此值会导致“编辑并继续”的各个组件向“输出窗口”>“调试”窗格显示大量详细日志记录 。