Visual Studion调试器指南---编辑并继续
“编辑并继续”是一种省时的功能,使您能够在程序处于中断模式时更改源代码。 当您通过选择一条类似 Continue 或 Step 的执行命令继续执行程序时,“编辑并继续”有限制地自动应用代码更改。 这允许您在调试会话期间更改代码,而不是停止程序,重新编译整个程序,再重新启动调试会话。
显式应用代码更改
在 Visual C++ 中,“编辑并继续”可以以两种方法应用代码更改。 代码更改可在选择执行命令时隐式应用,也可使用“应用代码更改”命令显式应用。当显式应用代码更改时,程序保持在中断模式下,不会执行。
在“调试”菜单中选择“应用代码更改”。安装 Visual Studio 时,“编辑并继续”在默认情况下是打开的。
启用和禁用“编辑并继续”
可以在“选项”对话框中禁用或启用“编辑并继续”。 无法在调试过程中更改此设置。“编辑并继续”仅在调试版本中起作用。 对于本机 C++,“编辑并继续”需要使用 /INCREMENTAL 选项,Visual C++ 环境中调试,如果设置了 /ZI 选项,仍可以使用“编辑并继续”。
启用/禁用“编辑并继续”
-
在“工具”菜单上,单击“选项”。
-
在“选项”对话框中打开“调试”节点,然后选择“编辑并继续”类别。
-
若要启用,请选择“启用‘编辑并继续’”复选框。 若要禁用,则清除该复选框。
提示
如果启用了 IntelliTrace 并且收集 IntelliTrace 事件和调用信息,则禁用编辑和继续。
-
单击“确定”。
停止代码更改
当“编辑并继续”处于应用代码更改的过程中时,您可以停止该操作。在托管代码中停止代码更改可能产生意外结果。 将更改应用到托管代码通常是一个很迅速的过程,因此极少需要在托管代码中停止代码更改。
停止应用代码更改
- 从“调试”菜单中选择“停止应用代码更改”。
该菜单项仅在应用代码更改时才可见。如果选择了改选项,就不会进行任何代码更改。
执行点
“编辑并继续”应用更改时,一些代码的更改会使执行点移动到新的位置。 “编辑并继续”尽可能正确地放置执行点,但是并非所有情况下的结果都正确。在 Visual C++ 中,当执行点更改时,会有一个对话框通知您。 在继续调试之前,应验证位置是否正确。 如果不正确,请使用“设置下一语句”命令。
Visual C++的编辑并继续
受支持的代码更改
“编辑并继续”处理大多数类型的代码更改。 但是,在程序执行期间,某些更改无法应用。 若要应用这些更改,必须停止执行并生成新版本的代码。
在调试会话期间不能应用下列 C/C++ 更改:
-
大多数的全局或静态数据的更改。
-
从其他计算机复制并且未在本地生成的可执行文件的更改。
-
影响一个对象(如类的数据成员)布局的数据类型的更改。
-
添加超过 64k 字节的新代码或数据。
-
添加要求在指令指针前存在构造函数的变量。
-
影响需要运行时初始化的代码的更改。
-
在某些实例中,添加异常处理程序。
-
资源文件的更改。
-
只读文件中的代码更改。
-
没有相应 PDB 文件的代码的更改。
-
没有对象文件的代码的更改。
如果进行了上面某项更改,然后尝试应用代码更改,“输出”窗口中就会出现错误或警告信息。
- “编辑并继续”不更新静态库。 如果您更改了静态库,仍会继续执行老版本,且不显示任何警告。
不支持的方案
在以下调试方案中,“编辑并继续”不可用:
-
在 Windows 98 上调试。
-
混合模式(本机/托管)调试。
-
SQL 调试。
-
调试 Dr. Watson 转储。
-
在未选择“在未经处理的异常上展开调用堆栈”选项的情况下,在发生未经处理的异常之后编辑代码。
-
使用“附加到”来调试应用程序,而不是单击“调试”菜单上的“开始”来运行应用程序。
-
调试优化后的代码。
-
当目标为 64 位应用程序时,调试托管代码。 如果希望使用“编辑并继续”,必须将目标平台设置为 x86 (“项目属性”对话框->“编译”选项卡->“高级编译器”设置。)
-
如果由于生成错误无法生成新版本的代码,则对旧版本的代码进行调试。
使用陈旧代码
在某些情况下,“编辑并继续”无法将代码更改立即应用于可执行文件,但如果您继续调试,则可能会在稍后应用代码更改。 当编辑某个调用当前函数的函数,或将多于 64 个字节的新变量添加到调用堆栈上的函数时,就会发生这种情况。
在这种情况下,调试器会继续执行原始代码(称为“陈旧代码”),直至可以应用更改。 陈旧的代码在单独的源窗口中作为临时源文件窗口显示,并带有一个类似 enc25.tmp 的标题。 编辑过的源继续在原始源窗口中显示。 当您尝试编辑陈旧的代码时,会显示一条警告信息。
启用/禁用陈旧代码警告
-
在“工具”菜单上,单击“选项”。
-
在“选项”对话框中选择“调试”文件夹。
-
在“编辑并继续”组中,选择或清除“就陈旧的代码发出警告”复选框。
-
单击“确定”。
链接限制
“编辑并继续”有两种类型的链接器限制:
-
默认情况下,“编辑并继续”在调试会话结束时重新链接到程序,以创建最新的可执行文件。 自动重新链接方面有一些限制。
-
有些链接器选项禁用“编辑并继续”。
下列链接器选项可禁用“编辑并继续”:
-
设置 /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) 文件的选项都会禁用“编辑并继续”,但不给出任何特定警告。
预编译头限制
默认情况下,“编辑并继续”在后台加载并处理预编译头,以加速对代码更改的处理。 加载预编译头需要分配物理内存,如果您正在一台 RAM 有限的计算机上进行编译,这可能会是一个问题。 在 Windows NT 或 Windows 2000 下,可以使用 Windows NT 任务管理器确定调试时可用的物理内存量,从而确定这是否会成为问题。 如果此数量大于预编译头的大小,则“编辑并继续”应没有问题。 如果此数量小于预编译头的大小,可以禁止“编辑并继续”在后台加载预编译头。
对“编辑并继续”禁用预编译头的后台加载
-
在“工具”菜单上,单击“选项”。
-
在“选项”对话框中选择“调试”节点,然后选择“编辑并继续”组。
-
清除“允许预编译”复选框。
-
单击“确定”。
特性限制
“编辑并继续”不重新生成接口定义 (IDL) 文件。 因此,调试时不反映对 IDL 特性的更改。 若要查看对 IDL 特性更改的结果,必须停止调试并重新生成应用程序。 如果 IDL 特性已更改,“编辑并继续”不生成错误或警告。
Visual C#的编辑并继续
使用 C# 的“编辑并继续”,可以一边进行调试一边在中断模式下更改代码。 不必停止并重新启动调试会话即可应用更改。 在运行模式下,源编辑器是只读的。“编辑并继续”支持在调试会话期间可能做出的大多数更改,但有某些例外。如果启用了“编辑并继续”,在使用调试器执行命令(如“继续”、“单步执行”、“设置下一语句”,或在调试器窗口中执行函数求值)时,会自动应用受支持的更改。
使用“编辑并继续”(C#)
使用 C# 的“编辑并继续”,可以一边进行调试一边在中断模式下更改代码。 不必停止并重新启动调试会话即可应用更改。在中断模式下进行更改时,将自动调用“编辑并继续”,然后选择调试器执行命令(如“继续”、“单步执行”或“设置下一语句”),或在调试器窗口中计算函数。在调试 64 位代码、Compact Framework、优化代码、本机/托管混合代码或 SQL Server 公共语言运行时 (CLR) 集成代码时不支持“编辑并继续”。 如果尝试在以上任何一种情况下应用代码更改,则调试器将显示一个对话框,其中说明不支持“编辑并继续”。
-
在中断模式下,对源代码进行修改。
-
在“调试”菜单中,单击“继续”、“单步执行”或“设置下一语句”,或在调试器窗口中计算函数。
这会编译新代码并继续调试新的代码。 有些更改不受“编辑并继续”支持。
启用/禁用“编辑并继续”跟VC++一样。
受支持的代码更改
“编辑并继续”处理方法体内的大多数类型的代码更改。 但是,方法体外的大多数更改以及方法体内的小部分更改在调试期间不能应用。 若要应用不受支持的更改,必须停止调试,重新开始修改后的代码。
在调试会话期间不能对 C# 代码应用下列更改:
-
对当前语句或任何其他活动语句的更改。
活动语句包括调用堆栈中的函数中为转至当前语句而调用过的任何语句。
当前语句在源窗口中以黄色背景标记。 其他活动语句以阴影背景标记,并且是只读的。 这些默认颜色可在“选项”对话框中更改。
-
对全局符号的更改,包括:
-
添加新类型。
-
在类型中添加方法。
-
更改类型的签名。
-
在类型中添加字段、事件或属性。
-
-
编辑匿名方法或任何包含匿名方法的方法。 这些方法以阴影背景标记。
-
添加新的匿名方法。
-
添加、移除或更改特性。
-
添加、移除或更改 using 指令。
-
移除或更改局部变量。 允许添加局部变量。
-
在活动语句前后添加 foreach、using 或 lock。
-
修改包含 yield return 或 yield break 语句的方法。
-
更改具有由匿名方法初始化的字段的构造函数。
不安全代码
对不安全代码的更改与对安全代码的更改有相同的限制,但它还包含一条附加的限制:
- “编辑并继续”不支持更改存在于包含 stackalloc 运算符的方法内的不安全代码。 这仅仅适用于活动方法。 当进行调试时,当前处于调用堆栈上的任何函数都是活动函数。
异常
“编辑并继续”支持对 catch、finally和 try 块的更改,但活动方法(比如当前处于调用堆栈中的方法)中的块除外。
-
如果活动函数是调用堆栈中最近使用的函数,则在该函数中“编辑并继续”不支持:
-
在活动语句的前后添加 catch 或 finally块。
-
添加嵌套级别大于六的嵌套异常处理程序。
-
-
如果活动函数不是调用堆栈中最近使用的函数,则在该函数中“编辑并继续”不支持:
-
在活动语句的前后添加 catch、finally 或 try块。
-
添加嵌套级别大于六的嵌套异常处理程序。
-
更改包含活动语句的 try块内的代码。
-
不支持的方案
在以下调试方案中,“编辑并继续”不可用:
-
调试 LINQ 代码。
-
混合模式(本机/托管)调试。
-
SQL 调试。
-
调试 Dr. Watson 转储。
-
在未选择“在未经处理的异常上展开调用堆栈”选项的情况下,在发生未经处理的异常之后编辑代码。
-
调试嵌入式运行时应用程序。
-
使用“附加到”来调试应用程序,而不是通过选择“调试”菜单上的“启动”来运行应用程序。
-
调试优化后的代码。
-
当目标为 64 位应用程序时,调试托管代码。 如果希望使用“编辑并继续”,必须将目标平台设置为 x86 (“项目 属性”对话框 ->“编译”选项卡 ->“高级编译器”设置。)
-
如果由于生成错误无法生成新版本的代码,则对旧版本的代码进行调试。