Question

I wrote some code with a lot of recursion, that takes quite a bit of time to complete. Whenever I "pause" the run to look at what's going on I get:

Cannot evaluate expression because the code of the current method is optimized.

I think I understand what that means. However, what puzzles me is that after I hit step, the code is not "optimized" anymore, and I can look at my variables. How does this happen? How can the code flip back and forth between optimized and non-optimzed code?

Was it helpful?

Solution

The Debugger uses FuncEval to allow you to "look at" variables. FuncEval requires threads to be stopped in managed code at a GarbageCollector safe point. Manually "pausing" the run in the IDE causes all threads to stop as soon as possible. Your highly recursive code will tend to stop at an unsafe point. Hence, the debugger is unable to evaluate expressions.

Pressing F10 will move to the next Funceval Safe point and will enable function evaluation.

For further information review the rules of FuncEval.

OTHER TIPS

While the Debug.Break() line is on top of the callstack you can't eval expressions. That's because that line is optimized. Press F10 to move to the next line - a valid line of code - and the watch will work.

You are probably trying to debug your app in release mode instead of debug mode, or you have optimizations turned on in your compile settings.

When the code is compiled with optimizations, certain variables are thrown away once they are no longer used in the function, which is why you are getting that message. In debug mode with optimizations disabled, you shouldn't get that error.

This drove me crazy. I tried attaching with Managed and Native code - no go.

This worked for me and I was finally able to evaluate all expressions :

  • Go into Project / Properties
  • Select the Build tab and click Advanced...
  • Make sure Debug Info is set to "full" (not pdb-only)
  • Debug your project - voila!

The below worked for me, thanks @Vin.

I had this issue when I was using VS 2015. My solution: configuration has (Debug) selected. I resolved this by unchecking the Optimize Code property under project properties.

Project (right Click)=> Properties => Build (tab) => uncheck Optimize code

Look for a function call with many params and try decreasing the number until debugging returns.

Make sure you do not have something like that

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

in your AssemblyInfo

Friend of a friend from Microsoft sent this: 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-more-than-256-argument-bytes-.aspx

The most likely problem is that your call stack is getting optimized because your method signature is too large.

Had the same problem but was able to resolve it by turning off exception trapping in the debugger. Click [Debug][Exceptions] and set the exceptions to "User-unhandled".

Normally I have this off but it comes in handy occasionally. I just need to remember to turn it off when I'm done.

I had this issue when I was using VS 2010. My solution configuration has (Debug) selected. I resolved this by unchecking the Optimize Code property under project properties. Project (right Click)=> Properties => Build (tab) => uncheck Optimize code

In my case I had 2 projects in my solution and was running a project that was not the startup project. When I changed it to startup project the debugging started to work again.

Hope it helps someone.

Assessment:

In .NET, “Function Evaluation (funceval)” is the ability of CLR to inject some arbitrary call while the debuggee is stopped somewhere. Funceval takes charge of the debugger’s chosen thread to execute requested method. Once funceval finishes, it fires a debug event. Technically, CLR have defined ways for debugger to issue a funceval.

CLR allows to initiate funceval only on those threads that are at GC safe point (i.e. when the thread will not block GC) and Funceval Safe (FESafe) point (i.e. where CLR can actually do the hijack for the funceval.) together. Thus, possible scenarios for CLR, a thread must be:

  1. stopped in managed code (and at a GC safe point): This implies that we cannot do a funceval in native code. Since, native code is outside the CLR’s control, it is unable to setup the funceval.

  2. stopped at a 1st chance or unhandled managed exception (and at a GC safe point): i.e at time of exception, to inspect as much as possible to determine why that exception occurred. (e.g: debugger may try to evaluate and see the Message property on raised exception.)

Overall, common ways to stop in managed code include stopping at a breakpoint, step, Debugger.Break call, intercepting an exception, or at a thread start. This helps in evaluating the method and expressions.

Possible resolutions: Based on the assessment, if thread is not at a FESafe and GCSafe points, CLR will not be able to hijack the thread to initiate funceval. Generally, following helps to make sure funceval initiates when expected:

Step #1:

Make sure that you are not trying to debug a “Release” build. Release is fully optimized and thus will lead to the error in discussion. By using the Standard toolbar or the Configuration Manager, you can switch between Debug & Release.

Step #2:

If you still get the error, Debug option might be set for optimization. Verify & Uncheck the “Optimize code” property under Project “Properties”:

Right click the Project Select option “Properties” Go to “Build” tab Uncheck the checkbox “Optimize code”

Step #3:

If you still get the error, Debug Info mode might be incorrect. Verify & set it to “full” under “Advanced Build Settings”:

Right click the Project Select option “Properties” Go to “Build” tab Click “Advanced” button Set “Debug Info” as “full”

Step #4:

If you still face the issue, try the following:

Do a “Clean” & then a “Rebuild” of your solution file While debugging: Go to modules window (VS Menu -> Debug -> Windows -> Modules) Find your assembly in the list of loaded modules. Check the Path listed against the loaded assembly is what you expect it to be Check the modified Timestamp of the file to confirm that the assembly was actually rebuilt Check whether or not the loaded module is optimized or not

Conclusion:

It’s not an error but an information based on certain settings and as designed based on how .NET runtime works.

in my case i was in release mode ones i changed to debug it all worked

I had a similar issue and it got resolved when I build the solution in Debug Mode and replaced the pdb file in the execution path.

I believe that what you are seeing is a result of the optimisations - sometimes a variable will be reused - particularly those that are created on the stack. For example, suppose you have a method that uses two (local) integers. The first integer is declared at the start of the method, and is used solely as a counter for a loop. Your second integer is used after the loop has been completed, and it stores the result of a calculation that is later written out to file. In this case, the optimiser MAY decide to reuse your first integer, saving the code needed for the second integer. When you try to look at the second integer early on, you get the message that you are asking about "Cannot evaluate expression". Though I cannot explain the exact circumstances, it is possible for the optimiser to transfer the value of the second integer into a separate stack item later on, resulting in you then being able to access the value from the debugger.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top