我正在尝试通过调试基于 API 项目模板的“开箱即用”WeatherForecast 应用程序来探索 ASP.NET Core 管道。
根据各种资源,我在 VS 中设置了以下配置:
工具->选项->调试->常规
- 启用 .NET Framework 源代码步进 - 已选中
- 启用源链接支持 - 已选中
- 抑制模块加载时的 JIT 优化 - 已选中
- 使用托管兼容模式(尝试选中/取消选中两种组合,但它似乎确实会影响任何内容)
- 启用 .NET Framework 源代码步进 - 已选中
工具->选项->调试->符号
- 加载所有模块,除非排除 - 已选择
- 作为符号的位置,我尝试了 Microsoft 符号服务器和集成到 JetBrains dotPeek 中的符号服务器
- 加载所有模块,除非排除 - 已选择
项目属性->调试->环境变量
- COMPLUS_JITMinOpts = 1 [根据 https://github.com/dotnet/runtime/issues/5767]。事实上,我相信这就是“抑制模块加载时的 JIT 优化”的作用。
- COMPLUS_ZapDisable = 1 [避免加载原生图像]
- COMPLUS_JITMinOpts = 1 [根据 https://github.com/dotnet/runtime/issues/5767]。事实上,我相信这就是“抑制模块加载时的 JIT 优化”的作用。
项目属性->构建
- 优化代码 - 未选中
- 优化代码 - 未选中
当我启动调试器并转到“调试”->“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)删除bin
和obj
文件夹,然后再次重建您的项目。
更新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/