为什么在从Visual Studio调试ASP.NET Core源代码时无法在堆栈中间看到局部变量

问题描述

我正在尝试通过调试基于API项目模板的“开箱即用” WeatherForecast应用程序来探索ASP.NET Core管道。

基于各种资源,我在VS中设置了以下配置:

  1. 工具->选项->调试->常规

    • 启用.NET Framework源代码步进-已选中
    • 启用Source Link支持-已选中
    • 禁止对模块负载进行JIT优化-已选中
    • 使用托管的兼容模式(尝试了两种组合的选中/未选中状态,但似乎没有任何影响)
  2. 工具->选项->调试->符号

    • 加载所有模块,除非已排除-已选定
    • 作为符号的位置,我尝试将Microsoft Symbol Server和Symbol Server集成到JetBrains dotpeek
  3. 项目属性->调试->环境变量

    • COMPLUS_JITMinopts = 1 [根据https://github.com/dotnet/runtime/issues/5767]。实际上,我相信这就是“抑制模块加载时的JIT优化”。
    • COMPLUS_Zapdisable = 1 [以避免加载本地图像]
  4. 项目属性->构建

当我启动调试器并转到Debug-> Windows-> Modules时,我可以看到所有ASP.NET Core dll均已加载符号,并且Optimized列设置为'No'。 但是,当我在控制器中遇到一个断点并遍历调用堆栈时,“本地”窗口中会出现很多错误

“无法获得局部变量或参数的值,因为它在此指令指针处不可用,可能是因为它已经被优化了”

我认为优化没有关闭,但是我可以在asp.net源代码中的函数内部找到一个断点,并观察局部变量。 当执行指针移到另一个函数时,该问题就产生了。一旦发生这种情况,这些局部变量将变得不可用。

在此线程https://github.com/aspnet/Mvc/issues/8375中,有人建议构建程序集的调试版本,但是我无法完全理解为什么需要这样做。 我的理解是,编译器通过删除nop指令和无效代码块来使IL代码更干净。真正的优化工作是由JIT完成的,并且可以由COMPLUS_JITMinopts和COMPLUS_Zapdisable标志进行控制。

在遍历堆栈时是否有办法避免这些“可能是因为它已被优化掉”消息?似乎我在这里缺少一些重要的概念,但是我不知道该去哪里看看。

我在VS2019(核心3.1)和VS2017(核心2.2)中都具有相同的行为

解决方法

尝试以下方法:

1):不确定您使用了哪些其他设置。为了给您提供更好的指导,建议您首先尝试在工具-> 导入和导出设置-> 全部重置下重置所有vs设置。设置,这样可以避免其他忽略的选项。

2)如果您使用发布模式,请输入项目属性-> 构建-> 高级->将调试信息更改为Full。使用与调试相同的模式。

3),请取消选中项目属性-> 构建下的优化代码复选框。

然后,然后在工具-> 调试下选中禁止模块负载上的JIT优化(仅受管理) -> 常规

4)删除binobj文件夹,然后再次重建项目。

5),您可以尝试convince the JIT compiler not to optimize the code is to use an INI file with the name of the assembly in the same folder the assembly is in with the contents

更新1

我的解决方案将使 Release (发布)模式更接近 Debug (调试)模式,并且由于它仍然看不到局部变量,因此恐怕无法根据需要更改Release模式。 / p>

让我详细解释一下:

特别是发布不是出于调试目的而生成的,它是最终产品的最佳发行版,如果发生以下情况,很可能会发生各种意外情况:您想查看代码中的堆栈和变量,这是真实的,所以我们不建议您这样做。

Debug 模式下,pdb文件非常大,它包含所需的所有调试类型,只有在调试模式下,您才能享受所有调试类型。调试模式用于调试项目,发布用于在调试项目没有问题时创建最终的优化版本,以减少发行量并使发布者更容易分发程序

结果,当在发布模式下进行调试时,无法避免出现问题。

我的解决方案是使 Release (发布)更接近Debug(调试)模式,并且Release的根本行为似乎无法更改,因此您必须使用Debug(调试)模式来监视局部变量以及它设计的该模式。正式调试。您应该使用Debug。

尝试一下