【发布时间】:2020-09-26 21:53:03
【问题描述】:
我正在尝试通过调试基于 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 优化”的作用。
-
项目属性->构建
- 优化代码 - 未选中
- 优化代码 - 未选中
当我启动调试器并转到 Debug->Windows->Modules 时,我可以看到所有 ASP.NET Core dll 都加载了符号,并且 Optimized 列设置为“No”。 但是,当我在控制器中遇到断点并遍历调用堆栈时,Locals 窗口中会出现很多错误:
'无法获取局部变量或参数的值,因为它在该指令指针处不可用,可能是因为它已被优化掉'
我认为优化没有关闭,但我可以在 asp.net 源代码中的函数内部打断点并观察局部变量。 当执行指针移动到不同的函数时,问题就出现了。一旦发生这种情况,这些局部变量就会变得不可用。
在这个线程https://github.com/aspnet/Mvc/issues/8375 中,有人建议构建程序集的调试版本,但是我无法完全理解为什么它是必要的。 我的理解是编译器只是通过删除 NOP 指令和死代码块使 IL 代码更干净。真正的优化工作由 JIT 完成,可以通过 COMPLUS_JITMinOpts 和 COMPLUS_ZapDisable 标志控制。
有没有办法在遍历堆栈时避免这些“可能是因为它已被优化掉”消息?似乎我在这里遗漏了一些重要的概念,但我不知道从哪里看。
我在 VS2019(核心 3.1)和 VS2017(核心 2.2)中都有相同的行为
【问题讨论】:
-
嗨,sergei,关于这个问题的任何更新?如果我的回答能帮助你处理和理解这个问题,请不要忘记accept it。如果没有,请随时告诉我们:)
-
嗨,佩里!提供的信息使我走上了正确的轨道。谢谢!最终,我从源代码构建了 asp.net 核心,并安装了基于 guideline 的最新调试二进制文件。一旦我添加了 Nuget.config(指向本地调试二进制文件)并将 Project Properties->Debug->Launch 设置为“Project”,我就能够看到堆栈中的变量。我接受了答案。
-
在我的例子中,变量实际上是有值的,直到它们进入抛出条件。由于某种原因,当该特定行被触发抛出异常时,所有局部变量都被优化掉了。我最终使用断点操作来写入一些数据以帮助追踪我的问题。我注意到的另一个令人讨厌的方面是,任何
Type或TypeInfo成员似乎仍然得到了优化。这似乎是一个早就应该解决的问题,但唉。
标签: .net asp.net-core .net-core visual-studio-debugging