Что «не может оценить выражение, потому что код текущего метода оптимизирован». иметь в виду?

StackOverflow https://stackoverflow.com/questions/131628

Вопрос

Я написал код с большим количеством рекурсии, выполнение которого занимает довольно много времени.Всякий раз, когда я «приостанавливаю» прогон, чтобы посмотреть, что происходит, я получаю:

Невозможно вычислить выражение, поскольку код текущего метода оптимизирован.

Кажется, я понимаю, что это значит.Однако меня озадачивает то, что после того, как я нажимаю «шаг», код больше не «оптимизируется», и я могу просматривать свои переменные.Как это произошло?Как код может переключаться между оптимизированным и неоптимизированным кодом?

Это было полезно?

Решение

Отладчик использует FuncEval, чтобы позволить вам «просматривать» переменные.FuncEval требует, чтобы потоки в управляемом коде останавливались в безопасной точке GarbageCollector.Приостановка выполнения вручную в среде IDE приводит к остановке всех потоков как можно скорее.Ваш высокорекурсивный код будет иметь тенденцию останавливаться в небезопасной точке.Следовательно, отладчик не может оценивать выражения.

Нажатие F10 приведет к переходу к следующей точке Funceval Safe и позволит оценить функцию.

Для получения дополнительной информации просмотрите правила FuncEval.

Другие советы

Пока строка Debug.Break() находится поверх стека вызовов, вы не можете оценивать выражения.Это потому, что эта линия оптимизирована.Нажмите F10, чтобы перейти к следующей строке — допустимой строке кода — и часы заработают.

Вероятно, вы пытаетесь отладить свое приложение в режиме выпуска, а не в режиме отладки, или в настройках компиляции включена оптимизация.

Когда код компилируется с оптимизацией, некоторые переменные выбрасываются, как только они больше не используются в функции, поэтому вы получаете это сообщение.В режиме отладки с отключенной оптимизацией вы не должны получить эту ошибку.

Это сводило меня с ума.Я попробовал подключиться с помощью управляемого и собственного кода — не получилось.

Это сработало для меня, и я наконец смог оценить все выражения:

  • Зайдите в Проект/Свойства.
  • Выберите вкладку «Построить» и нажмите «Дополнительно» ...
  • Убедитесь, что информация отладки установлена ​​на «Полный» (не только PDB)
  • Отладьте свой проект — вуаля!

Мне помогло следующее, спасибо @Vin.

У меня была эта проблема, когда я использовал VS 2015.Мое решение:в конфигурации выбрано (Отладка).Я решил эту проблему, сняв флажок Optimize Code недвижимость в рамках свойств проекта.

Проект (щелкните правой кнопкой мыши) => Свойства => Сборка (вкладка) => снимите флажок «Оптимизировать код».

Найдите вызов функции со многими параметрами и попробуйте уменьшить число, пока не возобновится отладка.

Убедитесь, что у вас нет чего-то подобного

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

в вашей AssemblyInfo

Друг друга из 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-more-than-256- аргумент-байты-.aspx

Наиболее вероятная проблема заключается в том, что ваш стек вызовов оптимизируется, поскольку сигнатура вашего метода слишком велика.

Была та же проблема, но удалось ее решить, отключив перехват исключений в отладчике.Нажмите [Отладка][Исключения] и установите для исключений значение «Необработанные пользователем».

Обычно я отключаю эту функцию, но иногда она может пригодиться.Мне просто нужно не забыть выключить его, когда я закончу.

У меня была эта проблема, когда я использовал VS 2010.В моей конфигурации решения выбрано (Отладка).Я решил эту проблему, сняв флажок со свойства «Оптимизировать код» в свойствах проекта.Проект (щелкните правой кнопкой мыши) => Свойства => Сборка (вкладка) => снимите флажок «Оптимизировать код».

В моем случае в моем решении было 2 проекта, и я запускал проект, который не был проектом запуска.Когда я изменил его на запускаемый проект, отладка снова начала работать.

Надеюсь, это кому-то поможет.

Оценка:

В .NET «Оценка функции (funceval)» — это возможность CLR внедрить произвольный вызов, пока отлаживаемый файл где-то остановлен.Funceval берет на себя управление выбранным потоком отладчика для выполнения запрошенного метода.Как только funceval завершается, он запускает событие отладки.Технически, CLR определила способы, с помощью которых отладчик может выдавать funceval.

CLR позволяет инициировать funceval только для тех потоков, которые находятся в безопасной точке GC (т.е.когда поток не будет блокировать GC) и точку Funceval Safe (FESafe) (т.е.где CLR действительно может перехватить funceval.) вместе.Таким образом, возможные сценарии для CLR, поток должен быть:

  1. остановлен в управляемом коде (и в безопасной точке GC):Это означает, что мы не можем выполнить функцию в машинном коде.Поскольку собственный код находится вне контроля CLR, он не может настроить funceval.

  2. остановлено при первом шансе или необработанном управляемом исключении (и в безопасной точке GC):то есть во время исключения, чтобы проверить как можно больше, чтобы определить, почему произошло это исключение.(например:отладчик может попытаться оценить и просмотреть свойство Message при возникновении исключения.)

В целом, распространенные способы остановки в управляемом коде включают остановку на точке останова, шаге, вызове Debugger.Break, перехвате исключения или при запуске потока.Это помогает в оценке метода и выражений.

Возможные решения:Согласно оценке, если поток не находится в точках FESafe и GCSafe, CLR не сможет перехватить поток для инициации funceval.Как правило, следующее помогает убедиться, что funceval запускается, когда ожидается:

Шаг 1:

Убедитесь, что вы не пытаетесь отладить «релизную» сборку.Релиз полностью оптимизирован и поэтому приведет к ошибке в обсуждении.Используя стандартную панель инструментов или диспетчер конфигурации, вы можете переключаться между отладкой и выпуском.

Шаг 2:

Если вы по-прежнему получаете сообщение об ошибке, возможно, для оптимизации установлен параметр «Отладка».Проверьте и снимите флажок со свойства «Оптимизировать код» в разделе «Свойства» проекта:

Щелкните правой кнопкой мыши параметр «Свойства» выберите «Свойства». Перейдите на вкладку «Создать». Снимите флажок «Оптимизировать код»

Шаг 3:

Если ошибка по-прежнему возникает, возможно, режим отладочной информации неверен.Проверьте и установите значение «полный» в разделе «Дополнительные настройки сборки»:

Щелкните правой кнопкой мыши параметр «Свойства» выберите «Проект». Перейдите к вкладке «Строительство». Нажмите кнопку «Дополнительно», набор «Информация отладки» как «Полное»

Шаг №4:

Если вы по-прежнему сталкиваетесь с проблемой, попробуйте следующее:

Сделайте «чистый», а затем «перестройка» вашего файла решения во время отладки:Перейдите в окно модулей (VS Menu -> Debug -> Windows -> Модули) Найдите свою сборку в списке загруженных модулей.Проверьте путь, перечисленный на загруженную сборку, - это то, что вы ожидаете, что проверьте измененную метку времени файла, чтобы подтвердить, что сборка была фактически восстановлена, проверьте, оптимизирован ли загруженный модуль или нет.

Заключение:

Это не ошибка, а информация, основанная на определенных настройках и разработанная с учетом того, как работает среда выполнения .NET.

в моем случае я был в режиме выпуска, который я изменил для отладки, все сработало

У меня была аналогичная проблема, и она была решена, когда я создал решение в режиме отладки и заменил файл pdb в пути выполнения.

Я считаю, что то, что вы видите, является результатом оптимизации — иногда переменная будет использоваться повторно, особенно те, которые создаются в стеке.Например, предположим, что у вас есть метод, который использует два (локальных) целых числа.Первое целое число объявляется в начале метода и используется исключительно как счетчик цикла.Второе целое число используется после завершения цикла и сохраняет результат вычисления, который позже записывается в файл.В этом случае оптимизатор МОЖЕТ решить повторно использовать ваше первое целое число, сохранив код, необходимый для второго целого числа.Когда вы попытаетесь посмотреть на второе целое число на раннем этапе, вы получите сообщение о том, что вы спрашиваете: «Невозможно вычислить выражение».Хотя я не могу объяснить точные обстоятельства, оптимизатор может позднее перенести значение второго целого числа в отдельный элемент стека, в результате чего вы сможете получить доступ к значению из отладчика.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top