是啥导致 Visual Studio 调试器使某些问题无法重现?

Posted

技术标签:

【中文标题】是啥导致 Visual Studio 调试器使某些问题无法重现?【英文标题】:What causes the Visual Studio Debugger to make some issues not reproducible?是什么导致 Visual Studio 调试器使某些问题无法重现? 【发布时间】:2013-11-06 16:47:41 【问题描述】:

环境:我有一个引用一些 Visual C++ 项目的 .NET 4.0 解决方案。视觉工作室 2010。

如果我构建我的解决方案并直接从 bin 目录运行生成的 .exe,我可以重现我的错误。但是,如果我在 Visual Studio 中点击“播放”按钮运行它(或者如果我运行进程并附加到它),我可以单步执行代码,一切正常。

作为参考,我遇到的问题是访问冲突,这肯定是在 C++ 代码中发生的。

但更广泛地说,我想知道将调试器附加到进程“修复”问题的其他原因。

【问题讨论】:

堆有问题。在 Release 模式下编译你的代码并在 VS 中调试它 运行绿色的“播放”按钮将使用 IDE 的环境。从目录执行将使用默认环境。我的猜测是,可能需要将一些 DLL 或依赖项(目录路径)添加到您的 %PATH% 环境变量中。 @Matt,我不认为这是一个堆问题 - 对于 C++,您需要在 DEBUG 编译配置中进行调试。 另一个棘手的事情。该问题只能在发布模式下重现。但是当我在发布模式下调试它时,问题就消失了。 可能是时间问题。例如。由后台线程引起的竞争条件。当您单步执行代码时,它会为后台线程提供工作时间。正常运行时,后台线程未及时完成。 我不认为使用其他调试器(例如 WinDbg)也无法重现它,虽然它的闪存比 IDE 集成调试器少得多,但实际上功能要强大得多。 【参考方案1】:

MS VS 像沙盒一样工作。当您在该沙箱中启动应用程序时,您的程序会从解决方案属性(或仅 VS 设置)继承所有设置。确保为环境提供的所有选项都是正确的。如果这不能解决问题,请仔细检查这些设置并考虑什么可以防止访问冲突并取消选中/选中它。

如果您使用的是外部 DLL,来自您系统的和来自 IDE 的可能有不同的版本。当然,它们可能在这两种情况下都有效,但也可能导致访问冲突或订阅超出范围等问题,具体取决于这些 dll 中的更改。

如果是 Windows 应用,请尝试启用/禁用 LargeAddressAware

如果您正在为另一台具有不同操作系统的机器编译东西,由于本机操作系统的内存处理变化,它可能会经常发生。内存有时可能是多块的、极度碎片化的,甚至是多设备的,因此只能使用专门针对目标操作系统/机器的编译来编译程序

调试模式使用 assert() 和其他直接链接到调试的东西。如果在调试中出现问题而不是在发布中出现问题,则意味着机器可以接受,但调试插入不能接受。在这种情况下,你就搞砸了,但如果它在其他调试器中似乎没有问题,那么......问题解决了,它的调试器问题,特别是如果没有调试选项的发布工作正常。

最累人的方法 - 尝试查明访问冲突地址并查看内存窗口内部您所指的内容。

在其他情况下,请向我们提供 sn-p,以便我们提供更多信息!


@Matt 这不可能是堆问题,它可能会发生,但极为罕见。

@Huytard 它不会发生,没有链接的 dll 的程序甚至不应该启动。

【讨论】:

如何启用 LargeAddressAware? 它仅适用于 x64 和 Linker>System>为此构建启用 LAA,您几乎没有机会通过此修复地址违规,但值得尝试跨度> @Matt 是的,但这是一个非常大的领域。如果你不小心,你几乎可以做任何事情来破坏堆。我假设如果他在.net 上工作,他可以​​处理坏指针:9【参考方案2】:

正确而简短的答案。 运行 Windows 更新。

正确而冗长的答案。

原来我的构建机器已经有一段时间没有更新了,并且使用的是过时版本的 Visual C++ 编译器。 .NET 4 的编译器中存在一个错误,其中静态构造函数没有在任何其他类型的构造函数之前被首先调用(仅在发布模式下)。

但这是最重要的! 如果您在 Visual Studio 调试器中运行该进程,或者您附加到远程进程。静态构造函数确实像他们应该的那样首先被调用! (因此使问题在调试环境中完全无法重现——即使在发布模式下)我通过在各处放置消息框以确定代码路径来发现问题。

http://connect.microsoft.com/VisualStudio/feedback/details/611716/c-cli-class-static-constructor-not-called-in-release-build

【讨论】:

【参考方案3】:
    运行绿色“播放”按钮将使用IDE's environment 从目录执行将使用default environment

我的猜测是可能需要将一些 DLL 或依赖项(目录路径)添加到您的 %PATH% 环境变量中。

一旦您确定依赖关系并仔细检查或使用 dependency walker 进行检查 - 您可以在批处理脚本中设置它们,然后调用您的应用程序。

例如:

@echo off
set PATH=%PATH%;C:\myLibs
call MyApp.exe

【讨论】:

以上是关于是啥导致 Visual Studio 调试器使某些问题无法重现?的主要内容,如果未能解决你的问题,请参考以下文章

译如何在 Visual Studio 中调试异步代码

使用Visual Studio Code开发和调试Java Burp扩展

Visual Studio实时调试器 是啥东西?

在 Visual Studio 中重命名某些内容时,如何查看“无法解决的冲突”是啥?

是啥导致 MS Visual Studio 无法识别构建错误?

是啥导致 Visual Studio 2017 中的文件名为空