Подтвердить что ты не робот

Отладка во время паузы и "не может оценивать выражение"

Используя Visual Studio, после присоединения к процессу и нажатия кнопки Pause (Break-All), вы переключаетесь на нужный поток и используете окно Quick Watch, чтобы проверить некоторые данные, скажем

MySingletonClass.Instance.Data

Иногда я либо получаю это:

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

или это (при попытке просмотра определенных свойств данных):

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

Честно говоря, мне все равно, я просто хочу посмотреть данные! Я знаю, что есть разные способы обойти это, а именно:

  • Установка точки останова в потоке и ожидание, пока она не пострадает (громоздко, не всегда возможно).
  • Получение дампа процесса и загрузка обратно в VS (даже тогда я все еще получаю вторую ошибку)
  • WinDbg

Учитывая, что вы можете видеть эти данные, если вы предположительно использовали windbg, почему мы все не можем использовать намного проще и красивее VS для проверки объектов при присоединении к процессу?

4b9b3361

Ответ 1

Почему мы не делаем этого? Мы не можем этого сделать, потому что окно просмотра Visual Studio не просто извлекает данные из памяти и отображает их. Он фактически выполняет управляемый код (это то, что означает "оценивать выражение" ). В частности, он почти всегда выполняет метод ToString() для отображения пользовательского результата.

Суть в том, что он выполняет этот код в процессе/потоке, который вы отлаживаете. Это гарантирует, что выражение оценивается так же, как если бы оно находилось в коде, который вы отлаживаете. Это оставляет недостаток, что он может выполняться только между управляемыми инструкциями, но не в том случае, если собственный код активен, а не в заблокированном потоке.

Что мы можем сделать с этим? Если вы действительно отлаживаете управляемое приложение и находитесь в собственном стеке, просто нажимайте F10 или Shift + F11, пока не вернетесь в управляемый код. Затем вы можете оценить выражения. Однако для полностью родных процессов и для потоков в заблокированном состоянии я не знаю об обходном пути.

Ответ 2

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

Дополнительная ссылка из обсуждения в OpenTK.

Ответ 3

Просто нажмите Shift-F11, пока на стеке не будет установлен фрейм управляемого стека, и вы сможете делать то, что хотите в VS.

В основном это сводится к тому, что при выполнении процесса небезопасно оценивать выражения в определенных точках или вы рискуете повредить среду выполнения. WinDbg не защищает время выполнения от вас. VS делает.

Ответ 4

Проблема заключается в том, что это не данные, которые вы хотите увидеть, это результат запуска некоторого кода. В свойствах .Net на самом деле просто маскируются методы, поэтому для получения значения свойства Visual Studio необходимо выполнить код приложения (эта функция называется FuncEval).

Этот код должен запускаться в каком-то потоке, а VS - это то, что для этого используется один из приложений. Существует ряд ситуаций, где VS не может запустить код для получения результата, и именно тогда вы видите сообщения об ошибках, я говорю.

Ответ 5

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

Заметьте, что это обычно не работает.

Ответ 6

Если ваш проект является клиентским сервером, попробуйте перезагрузить ссылку MySql.Data.dll

Ответ 7

Я знаю, что это kludge, но я доволен тем, как он работает. В конце моего метода Main(), который изначально запускает все и создает все другие структуры данных и потоки, а затем завершается, я придерживаюсь этого:

        while (true)
        {
            // This infinite while loop just gives me a convenient place for a 
            // breakpoint, so I can see everything everywhere during debugging.
            Thread.Sleep(100);
        }

Вместо того, чтобы делать "Break All", я просто придерживаюсь точки останова на фигурной скобке {. Программа прерывается. У меня есть поток и ссылка на все, поэтому я могу легко просматривать все структуры данных и все потоки, видеть все везде.