.net - 为什么在 Visual Studio 中调试 ASP.NET Core 源代码时看不到堆栈中间的局部变量

标签 .net asp.net-core .net-core visual-studio-debugging

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

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

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

    • 启用 .NET Framework 源代码步进 - 已选中
    • 启用源链接支持 - 已选中
    • 抑制模块加载时的 JIT 优化 - 已选中
    • 使用托管兼容模式(尝试选中/取消选中两种组合,但它似乎确实会影响任何内容)
  2. 工具->选项->调试->符号

    • 加载所有模块,除非排除 - 已选择
    • 作为符号的位置,我尝试了 Microsoft 符号服务器和集成到 JetBrains dotPeek 中的符号服务器
  3. 项目属性->调试->环境变量

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

    • 优化代码 - 未选中

当我启动调试器并转到“调试”->“Windows”->“模块”时,我可以看到所有 ASP.NET Core dll 都已加载符号,并且“优化”列设置为“否”。 但是,当我在 Controller 中命中断点并遍历调用堆栈时,“局部变量”窗口中出现很多错误:

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

我认为优化没有关闭,但我可以在 ASP.NET 源代码中的函数内部命中断点并观察局部变量。 当执行指针移动到不同的函数时,问题就会出现。一旦发生这种情况,这些局部变量就变得不可用。

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

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

我在 VS2019(核心 3.1)和 VS2017(核心 2.2)中得到了相同的行为

最佳答案

尝试这些:

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

2) 如果您使用Release模式,请进入Project Properties-->Build--> 高级--> 将调试信息更改为完整。使用与调试相同的模式。

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模式无法按照我们想要的方式更改。

让我更详细地解释一下:

具体发布模式并不是为了调试目的而产生的,它是最终产品的最佳发布版本,显然,如果您想要查看代码中的堆栈和变量,这是真实存在的,因此我们不建议这样做。

调试模式下,pdb文件非常大,它包含了你想要的所有调试类型,只有在 Debug模式下,你才能享受所有调试类型。 debug模式用于调试项目,Release是在调试项目没有问题的情况下创建最终的优化版本,以减少release,方便发布者分发程序.

因此,在Release模式下调试时,无法避免出现问题。

我的解决方案是让Release更接近于Debug模式,似乎Release的根本行为无法改变,所以你必须使用Debug模式来观察局部变量以及它设计的这种模式正式调试。您应该使用调试。

尝试一下

关于.net - 为什么在 Visual Studio 中调试 ASP.NET Core 源代码时看不到堆栈中间的局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64082846/

相关文章:

.net - 为 .Net Core 3.1 应用程序配置 log4net 的最简单的正确方法

.net - 使用官方 Microsoft dotnet docker 镜像在 linux 上构建 dotnet

c# - 创建分组中继器布局

c# - 如何在 C# 中声明不可变变量(值)?

c# - .NET,C# : How to add a custom serialization attribute that acts as ISerializable interface

docker - 如何在 docker 图像中包含声纳扫描仪

.net - 如何重构在 .NET 中序列化的类?

asp.net-core - 如何正确使用身份服务器 4 的自省(introspection)端点?

c# - 项目中不存在目标 "GetCopyToPublishDirectoryItems"。

c# - 在 .NET Core 测试项目中构建时禁用/阻止 XUnit 警告