繁体   English   中英

什么“无法评估表达式,因为当前方法的代码已经过优化。”是什么意思?

[英]What does “Cannot evaluate expression because the code of the current method is optimized.” mean?

我写了一些带有大量递归的代码,需要花费很多时间才能完成。 每当我“暂停”运行以查看我得到的结果:

无法计算表达式,因为当前方法的代码已经过优化。

我想我明白这意味着什么。 然而,让我感到困惑的是,在我点击步骤之后,代码不再“优化”了,我可以查看我的变量。 这是怎么发生的? 代码如何在优化代码和非优化代码之间来回切换?

虽然Debug.Break()行位于callstack之上,但您无法eval表达式。 那是因为该线路已经过优化。 按F10移动到下一行 - 一行有效的代码 - 手表将起作用。

您可能尝试在发布模式而不是调试模式下调试应用程序,或者在编译设置中打开了优化。

当使用优化编译代码时,某些变量一旦在函数中不再使用就会被丢弃,这就是您获取该消息的原因。 在禁用优化的调试模式下,您不应该收到该错误。

调试器使用FuncEval来“查看”变量。 FuncEval要求在GarbageCollector安全点的托管代码中停止线程。 手动“暂停”IDE中的运行会导致所有线程尽快停止。 您的高递归代码将倾向于停在不安全的位置。 因此,调试器无法计算表达式。

按F10将移至下一个Funceval Safe点并启用功能评估。

有关详细信息,请查看FuncEval规则

这让我发疯了。 我尝试使用Managed和Native代码附加 - 没有去。

这对我有用,我终于能够评估所有表达式:

  • 进入项目/属性
  • 选择Build选项卡,然后单击Advanced ...
  • 确保Debug Info设置为“full”(不是pdb-only)
  • 调试你的项目 - 瞧!

以下对我有用,谢谢@Vin。

我在使用VS 2015时遇到了这个问题。我的解决方案:配置已选中(Debug)。 我通过取消选中项目属性下的Optimize Code属性来解决这个问题。

项目(右键单击)=>属性=>构建(选项卡)=>取消选中优化代码

查找具有许多参数的函数调用,并尝试减少该数字直到调试返回。

确保你没有那样的东西

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]

在你的AssemblyInfo

我在使用VS 2010时遇到了这个问题。我的解决方案配置已选中(Debug)。 我通过取消选中项目属性下的Optimize Code属性来解决这个问题。 项目(右键单击)=>属性=>构建(选项卡)=>取消选中优化代码

来自Microsoft的朋友的朋友发送了这封信http//blogs.msdn.com/rmbyers/archive/2008/08/16/Func_2D00_eval-can-fail-while-stopped-in-a-non_2D00_optimized-managed-method-that -pushes-更比256参数字节-的.aspx

最可能的问题是您的调用堆栈正在优化,因为您的方法签名太大。

有同样的问题,但能够通过关闭调试器中的异常捕获来解决它。 单击[Debug] [Exceptions]并将例外设置为“User-unhandled”。

通常情况下,我有这个,但它偶尔会派上用场。 我只需要记得在我完成时关掉它。

在我的情况下,我在我的解决方案中有2个项目,并且正在运行一个不是启动项目的项目。 当我将其更改为启动项目时,调试开始再次起作用。

希望它可以帮助某人。

评定:

在.NET中,“函数评估(funceval)”是CLR在某个地方停止调试对象时注入一些任意调用的能力。 Funceval负责调试器选择的线程以执行请求的方法。 一旦funceval完成,它就会触发一个调试事件。 从技术上讲,CLR已经定义了调试器发出funceval的方法。

CLR允许仅在那些处于GC安全点(即线程不会阻塞GC)和Funceval Safe(FESafe)点(即CLR实际上可以对funceval进行劫持的位置)的线程上启动funceval。 因此,CLR的可能场景,一个线程必须是:

  1. 在托管代码中停止(并在GC安全点):这意味着我们不能在本机代码中执行funceval。 由于本机代码不在CLR的控件之内,因此无法设置funceval。

  2. 停在第一次机会或未处理的托管异常(并在GC安全点):即在异常时,尽可能地检查以确定异常发生的原因。 (例如:调试器可能会尝试评估并查看引发异常的Message属性。)

总的来说,在托管代码中停止的常见方法包括在断点处停止,步骤,Debugger.Break调用,拦截异常或在线程启动时。 这有助于评估方法和表达式。

可能的解决方案:根据评估,如果线程不在FESafe和GCSafe点,CLR将无法劫持线程以启动funceval。 通常,以下有助于确保funceval在预期时启动:

步骤1:

确保您没有尝试调试“发布”版本。 发布已完全优化,因此将导致讨论中的错误。 通过使用标准工具栏或配置管理器,您可以在调试和发布之间切换。

第2步:

如果仍然出现错误,可能会设置Debug选项进行优化。 在项目“属性”下验证并取消选中“优化代码”属性:

右键单击“项目选择”选项“属性”转到“构建”选项卡取消选中“优化代码”复选框

第3步:

如果仍然出现错误,则调试信息模式可能不正确。 在“高级构建设置”下验证并将其设置为“完整”:

右键单击Project Select选项“Properties”转到“Build”选项卡单击“Advanced”按钮将“Debug Info”设置为“full”

第4步:

如果您仍然遇到此问题,请尝试以下操作:

执行“清理”然后“重建”解决方案文件调试时:转到模块窗口(VS菜单 - >调试 - > Windows - >模块)在已加载模块列表中找到您的程序集。 检查列出的已加载程序集的路径是否符合预期检查文件的已修改时间戳以确认程序集实际已重建检查已加载的模块是否已优化

结论:

这不是错误,而是基于某些设置的信息,也是基于.NET运行时的工作原理设计的。

在我的情况下,我是在发布模式,我改变调试它都工作

我有一个类似的问题,当我在调试模式下构建解决方案并在执行路径中替换pdb文件时,它得到了解决。

我相信你所看到的是优化的结果 - 有时一个变量将被重用 - 特别是那些在堆栈上创建的变量。 例如,假设您有一个使用两个(本地)整数的方法。 第一个整数在方法的开头声明,并且仅用作循环的计数器。 在循环完成后使用第二个整数,它存储稍后写入文件的计算结果。 在这种情况下,优化器可以决定重用第一个整数,保存第二个整数所需的代码。 当您尝试在早期查看第二个整数时,您会收到有关“无法计算表达式”的消息。 虽然我无法解释具体情况,但优化器可能会在稍后将第二个整数的值传输到单独的堆栈项中,从而使您能够从调试器访问该值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM