支持的代码更改(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 编译的本机应用 (增强优化调试)

  • 使用 MSVC v120 工具集和 C/C++ /bigobj 选项的项目。 仅 MSVC v140 和更高版本的构建工具支持编辑并继续功能。

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

  • JavaScript 调试。

  • SQL 调试。

  • 调试内存转储文件。

  • 在未经处理的异常发生后编辑代码,当未选择在未处理的异常时展开调用堆栈选项时。

  • 通过使用 Attach to 调试应用,而不是通过选择“调试”菜单上的“开始”来运行应用。

  • 调试优化的代码。

  • 在新版本因生成错误而无法生成之后调试旧版本的代码。

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

  • 遗留体系架构/MSVC工具集。 使用 MSVC v140 工具集,默认调试器支持对 X86 和 X64 应用程序进行编辑并继续。 旧版工具集仅支持 X86 应用程序。 早于 MSVC v120 的工具集应通过检查“调试 > 选项 > 常规 > 使用本机兼容性模式”来使用旧版调试器,以便使用“编辑并继续”。

链接限制

禁用编辑并继续功能的链接器选项

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

  • 设置 /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. 清除 调试后重新链接代码更改 复选框。

预编译标头限制

默认情况下,Edit and Continue 在后台加载并处理预编译头,从而加快代码更改的处理速度。 加载预编译标头需要分配物理内存,如果在具有有限 RAM 的计算机上进行编译,则这可能会出现问题。 可以通过使用 Windows 任务管理器来确定在调试时可用的物理内存量,来确定这是否是个问题。 如果此数量大于预编译标头的大小,则“编辑并继续”不应有问题。 如果数量小于预编译标头的大小,则可以阻止 Edit and Continue 在后台加载预编译标头。

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

  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

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