运行 Visual Studio 中托管的调试应用程序和直接运行它有啥区别?
Posted
技术标签:
【中文标题】运行 Visual Studio 中托管的调试应用程序和直接运行它有啥区别?【英文标题】:What's the difference between running a debug app hosted in Visual Studio and running it directly?运行 Visual Studio 中托管的调试应用程序和直接运行它有什么区别? 【发布时间】:2011-03-15 12:02:12 【问题描述】:我有一个在 .Net framework 4 上运行的应用程序,我的应用程序运行托管和非托管代码。 UDP 套接字与自定义通信堆栈一起使用,以与我们的自定义硬件通信。当应用程序从 Visual Studio 运行时,一切都很好,但是当它自己运行时,它经常冻结。我已经在 Windows XP SP3 和 Windows 7 SP1 上看到了这种行为。当应用程序被冻结时,我可以看到它在我的大多数线程中都卡在了 ntdll.dll 中。我在另一个问题线程中被告知这是正常的,死锁仍然是由我的代码引起的。
这很难调试,因为我只能附加到应用程序并在本机模式下暂停它,所以我看到的只是反汇编。我正在寻找任何可以帮助我的提示。那么,有没有人知道什么会导致应用程序在直接运行时与使用 F5 从 Visual Studio 运行时冻结?我在某处读到,在托管代码中,GC 的行为不同,有什么区别?此外,对于非托管代码,我收集到内存的初始化方式不同。又有什么区别呢?
非常感谢任何帮助!
Seb
【问题讨论】:
你能下载ntdll.dll的符号吗?这至少会告诉您在附加调试器时您的应用程序卡在什么功能上?如果您加载了足够多的符号,那么调用堆栈开始看起来很有意义。也许这可以说明您的问题。 只是为了确保:当您“自行”运行应用程序时,您是在运行调试版本还是发布版本? 【参考方案1】:在没有调试器的情况下运行 Release 构建时的不同之处在于启用了 JIT 优化器。代码运行得更快。这与您的问题有很强的相关性,线程问题对时间敏感。当您的代码仍在您的开发机器上运行时,这会出错(我相信您不会)算您自己幸运,真正令人讨厌的线程问题是每周在您客户的机器上弄乱您的程序一次。
使这个问题可调试仍然是解决它的最重要方法。除了 Tools + Attach to Process,启动调试器的另一种方法是在代码中使用 System.Diagnostics.Debugger.Launch()。您将看到一个对话框,让您选择调试器。
另一种不需要附加调试器的方法是将 VS 切换到 Release 版本。使用工具 + 选项、调试、常规并取消勾选“在模块加载时抑制 JIT 优化”。现在按 F5 运行您的程序,启用优化器并预先附加调试器。由于附加调试器本身会导致时序差异,因此仍然不是很糟糕。
解决并发错误的另一种常用方法是在代码中添加日志记录。每当它获得锁时写一行。运气好的话,你会很快找到死锁的原因。如果你不那么幸运,日志记录会改变线程时序,足以使死锁消失。有很多程序都启用了日志记录,因为这是保持它们运行的唯一方法。
代码审查是另一种方法,尤其是由其他人完成时。最后但并非最不重要的一点是,考虑线程是否真的是您应用程序中的最佳解决方案。唠叨“我真的解决了吗?”感觉永远不会消失,证明线程代码没有缺陷几乎是不可能的。
【讨论】:
【参考方案2】:此类问题的原因可能是死锁或竞争条件。当您调试应用程序时它们会消失,因为断点和执行中断会改变某些代码路径的执行持续时间。 我不明白,为什么你只能在本机模式下附加。托管应用程序甚至支持远程调试。
【讨论】:
它是托管代码和非托管代码的混合体。我不确定我只能在本机模式下附加这一事实是否表明冻结发生在 C++ 代码中。 @Ssebu:不,这不是原因。我假设,应用程序已经在运行,并且您正在使用 Debug -> Attach to process。它在“附加到”的文本框中读起来像什么?您的应用程序的“类型”列的值是多少? 列类型为 T-SQL, Managed (v4.0.30319), x86。如果我尝试附加然后点击暂停按钮,则会出现以下错误消息:“无法中断执行。此进程当前未执行您选择调试的代码类型。”以上是关于运行 Visual Studio 中托管的调试应用程序和直接运行它有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
在 Visual Studio 中运行 .Net 1.1 应用程序时出错
.NET Web应用配置本地IIS(实现Visual Studio离线运行与调试)