Visual Studio 2010调试器跳过方法并且不在断点处停止

29

我的Visual Studio 2010调试器有时会表现得非常奇怪...

有时它不会在断点处停止,但当它停止时,我想进入一个方法,调试器却只是跳过它。此外,在那些被跳过的方法中设置的断点也被忽略了。

当出现这种奇怪的行为时,它也不会在异常处中断,而只是忽略它们。

我已经尝试重新构建项目,重置Visual Studio设置,并禁用了调试器设置,如“仅在我的代码中中断”,但没有任何效果。

我该如何解决这个问题?


以发布配置的形式发布?在发布配置中,优化器可以删除一些代码,因此调试可能会出现问题。 - Andriy Tylychko
这种情况是在一种调试会话中发生,还是随机发生的?例如,如果您正在尝试通过附加到进程来调试运行中的服务,或者只是尝试在调试器中运行代码? - Jesse McCulloch
@robin hood 配置已设置为调试模式 @Jesse McCulloch 我只是在调试器中运行代码,但它会随机发生。 - Flagbug
这在VS2008 SP1中也是一个问题。虽然有一个热补丁,但并不是所有的修复程序都被检查到主干中。Service Pack 1即将推出beta版。你可以尝试一下,但不要在生产机器上这样做。 - Hans Passant
12个回答

39

以下是一些可能导致Visual Studio无法进入特定方法的原因和解决方法:

  • 仅限我的代码模式已启用。在某些情况下,“仅限我的代码”设置会阻止您进入方法/属性。要避免这种情况,可以在调试器选项页面中禁用“仅限我的代码”(工具->选项->调试器->取消选中“仅限我的代码”)。
  • 目标方法的符号未加载。如果目标方法是另一个DLL的一部分,则该DLL的符号可能未加载,因此默认情况下Visual Studio将无法进入该方法。要强制加载符号,请打开模块视图(调试器->窗口->模块),导航到包含该方法的DLL,右键单击并加载符号。
  • 该方法明确标记为调试器属性,例如DebuggerNonUserCode,这会导致调试器跳过该方法。
  • 该方法实际上是属性或运算符,并且您启用了“跨越属性和运算符进行步骤”设置(这是默认设置)。可以通过调试器选项对话框禁用此功能。

2
在Visual Basic Express 2005中(别问我为什么),似乎没有“工具->选项->调试器->'只有我的代码'”选项。一个解决方案是在文件“C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\VBExpress\Profiles\VBExpress.vssettings”的包含“JustMyCode”的行中将“1”更改为“0”,然后将该文件导入到Visual Basic Express 2005中。详细信息请参见Josh Dannemann在*如何在Visual Studio 2005中禁用“只有我的代码”*的评论,可能还可以在Stack Overflow上找到相关内容。 - Peter Mortensen
我现在已经在 如何在Visual Basic 2005 Express中禁用“仅限我的代码”? 中记录了它。 - Peter Mortensen
1
你列表中可以再加上一个可能性,那就是DebuggerStepThrough属性。这个属性通常被生成器添加到生成的代码(例如XML生成的代码)中。 - Alex Marshall

4

另一个令人困惑的问题是使用yield return操作符的迭代器方法,因为它们被C#编译器重新编写成一种步进(F11)时相当于"无操作"的方式。

您必须等待迭代发生才能中断该方法的代码。


4
在我的情况下,需要在“工具”->“选项”->“调试器”中取消“跳过属性和操作符”的勾选,然后就可以顺利地进行步入调试了。

3
我已经找到了解决问题的方法,而且非常简单:在我的解决方案构建配置中,那些被忽略的方法所在的项目的“构建”复选框没有被勾选。我现在已经勾选了它,现在一切都正常了。

1
构建配置在哪里,我在VS 2013上。 - The Beast

2
检查最重要的是在方法中尝试放置新断点时,如果断点像其他断点一样填充红色,或者半填充或具有特殊的“外观”,则是否拒绝步入。如果是这样,请悬停在您创建的断点上查找原因。
如果断点看起来正常,但仍然无法进入方法,请尝试清除阴影副本缓存:http://weblogs.asp.net/mreynolds/archive/2003/08/11/23576.aspx 另一个要尝试的事情是确保您确实正在使用刚刚重新编译的DLL,在您无法停止的方法中添加MessageBox.Show(或类似内容),并确保您获得此框。

我已经尝试了您的建议,使用消息框,确实在运行程序时没有出现任何消息框。现在我将尝试找出为什么该方法未被正确调用的原因。 - Flagbug
正如Jared所建议的那样,监视这些问题的最佳方法是使用模块窗口(调试器->窗口->模块)来检查加载的DLL是否确实是您刚刚构建的DLL-通过查看DLL的上次修改日期来验证。当我遇到这种类型的问题时,对我非常有用的一件事是使用Everything(http://www.voidtools.com/,程序员必备的免费工具)搜索DLL名称,并按修改日期排序。您可能会找到刚刚重建的DLL的路径以及应用程序正在加载的旧版本DLL的路径。 - Omer Raviv
调试器 -> 窗口 -> 模块 对我很有用 - 我的 DLL 文件由于其他团队对其项目的最近更改而处于奇怪的位置,并且一些旧版本的 DLL 被选中。 - Galadrius Krunthar

2

我曾经为此苦苦挣扎。所给出的答案都对我没有用。最终,我通过以下步骤使它工作:

  1. 确保项目处于调试模式(所有项目)
  2. 从Windows进入命令提示符,并确保以管理员身份运行
  3. 导航到 c:\windows\syswow64\ (或包含 gacUtil.exe 的文件夹)
  4. 运行以下命令(将下面的路径替换为您的 DLL 的调试输出版本所在的位置)。

gacutil /i "C:\Users\John\Documents\Visual Studio 2008\Projects\Project1\Project1\bin\Debug\MyAppDLL.dll"

您应该会得到“程序集已成功添加到缓存”

现在运行您的项目,您应该能够进入 DLL 代码。


1

我刚刚发现了问题的另一个原因和解决方法。我正在使用Visual Studio 2010中的C++创建Windows Forms应用程序。我正在使用FreeType库和一些依赖于它的代码,由于各种原因,这些代码必须选择“不支持公共语言运行时”进行编译(属性 -> 配置属性 -> 常规)。我无法在这个非CLR代码中设置断点。

解决方法是主应用程序必须使用“公共语言运行时支持(/clr)”进行编译,而不是“纯MSIL公共语言运行时支持(/clr:pure)”。这立即解决了问题。我现在可以调试并命中非CLR代码中的断点,包括FreeType C代码。


1

我猜测你在解决方案中通过浏览dll文件(project/bin/debug/mydll.dll)来引用另一个项目,而不是添加“项目引用”。如果你的解决方案中有多个项目,请删除所有对每个项目的引用。然后,在“添加引用”对话框中,点击“添加项目引用”选项卡,并选择要引用的项目。

项目引用总是在新构建时更新。但是,如果你浏览到bin/release并添加对该目录中dll文件的引用,当你切换到调试模式并添加代码并尝试调试它时,旧版本的发布dll将加载到应用程序域中,VS将无法命中任何断点(你会注意到断点是空圆圈,工具提示将显示有关未加载代码的信息)。


0

我最近也遇到了同样的问题。虽然不确定自己具体做了什么。尝试“物理”清理你的解决方案,即从解决方案的所有项目中删除所有 bin 目录。这通常有助于解决许多问题。


0
尝试在工具->选项->调试->常规中禁用“要求源文件完全匹配”的选项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接