Visual studio переменная удалена в процессе оптимизации и недоступна
Даже если я создаю чистый проект WinForms, Edit and Continue не работает и выдает ошибку:
Изменения не допускаются, если отладчик подключен к уже запущенному процессу или отлаживаемый код был оптимизирован во время сборки или выполнения.
- Параметр «Изменить и продолжить» отмечен в Инструменты → Параметры → Отладка.
- Оптимизация не включена.
- Похоже, что никакого управляемого профилировщика не установлено.
- Я работаю в режиме отладки
- Я использую процессор x64 и 32-разрядную версию Windows XP, но установка целевой платформы на x86, а не на AnyCpu, не помогает.
- Восстановление установки Visual Studio не помогает.
Я также нашел эту статью на сайте MSDN:
Отладка в Windows 98.
Отладка в смешанном режиме (собственная / управляемая).
Отладка SQL.
Отладка дампа доктора Ватсона.
Редактирование кода после необработанного исключения, когда опция «Разматывать стек вызовов при необработанных исключениях» не выбрана.
Отладка встроенного приложения среды выполнения.
Отладка приложения с помощью Attach to, а не запуск приложения с помощью Start из меню Debug.
Отладка оптимизированного кода.
Отладка управляемого кода, когда целью является 64-разрядное приложение. Если вы хотите использовать Edit and Continue, вы должны установить цель на x86. (Свойства проекта, вкладка «Компиляция», настройка расширенного компилятора.).
Отладка старой версии вашего кода после сбоя сборки новой версии из-за ошибок сборки.
Но я могу ответить «Нет» на каждый пункт в этом списке.
Раньше работало, но несколько дней назад перестало работать, и я не знаю, в чем может быть причина.
Действительно ли метод, который вы пытаетесь использовать для E&C, короткий? возможно, он был встроен (хотя я думаю, что встраивание не происходит при отладке) Он не работает ни с какими методами, ни с очень короткими, ни с очень длинными. Думаю, я должен добавить, что E&C - довольно сложная функция. Матрица тестов отладчика огромна, и заставить E&C работать в каждой комбинации будет чрезвычайно сложно. Но это тоже действительно важная функция, поэтому мы взяли на себя множество ограничений, чтобы убедиться, что она будет выпущена. В рамках намеренных ограничений, которые мы наложили на него, это одна из самых качественных функций, которые мы предоставили.Наконец-то я решил проблему: УДАЛИТЬ Gallio
У Gallio, похоже, довольно много шероховатостей, и лучше не использовать MbUnit 3.0, а использовать инфраструктуру MbUnit 2.0, но использовать бегун gallio, который вы запускаете без установки из установщика (который также установил плагин Visual Studio).
Между прочим, проблема возникла даже после "отключения" самого плагина Gallio. Только удаление решило проблему.
PS. Отредактировано nightcoder:
В моем случае, наконец, помогло отключение TypeMock Isolator ( mocking framework) ! Edit & Continue теперь работает .
Вот ответ от службы поддержки TypeMock:
Изучив проблему редактирования и продолжения и поговорив о ней с Microsoft, мы пришли к выводу, что ее нельзя решить для Isolator. Isolator реализует профилировщик CLR, и, согласно нашим исследованиям, после того, как профилировщик CLR включен и подключен, редактирование и продолжение автоматически отключаются. К сожалению, это больше не считается ошибкой, а скорее ограничением Isolator.
Другие применимые решения
Убедитесь, что для системной переменной COR_ENABLE_PROFILING не задано значение 1 . Некоторые профилировщики устанавливают это при установке и оставляют после удаления. Откройте командную строку и введите, set чтобы быстро проверить, затронута ли ваша система, если да, удалите переменную или установите для нее значение 0 :
- В Windows 8 и выше найдите Система (Панель управления).
- Щелкните ссылку Дополнительные параметры системы .
- Щелкните Переменные среды .
- удалять COR_ENABLE_PROFILING
* под «вами» я имею в виду посетителя страницы, который бьет головой по клавиатуре, чтобы найти решение.
Не стесняйтесь редактировать этот ответ, чтобы добавить обходной путь, если он не указан здесь!
Отображаемые диалоговые окна и команды меню могут отличаться от описанных в справке в зависимости от текущих параметров или выпуска. Чтобы изменить параметры, в меню "Сервис" выберите команду "Импорт и экспорт параметров". Дополнительные сведения см. в разделе Сброс параметров.
Параметр компилятора /Zo, позволяющий улучшить оптимизированный процесс отладки и впервые появившийся в Visual Studio с обновлением 3, генерирует расширенные сведения по отладке для оптимизированного кода (проекты, которые не были собраны с параметром компилятора /Od). Дополнительные сведения см. в разделе Параметры /O (оптимизация кода). Это обеспечивает улучшенную поддержку отладки локальных переменных и встроенных функций.
Когда используется параметр компилятора /Zo, режим Изменить и продолжить отключается.
Когда компилятор оптимизирует код, он перераспределяет и реорганизует инструкции. Это приводит к повышению эффективности скомпилированного кода. В связи с этим перераспределением отладчик не всегда может идентифицировать исходный код, соответствующий набору инструкций.
Оптимизация может повлиять на:
Локальные переменные (могут быть удалены оптимизатором или перемещены в места, недоступные для отладки).
Код внутри функций (изменяется расположение при слиянии оптимизатором блоков кода).
Имена функций в фреймах стека вызовов (могут оказаться некорректными при слиянии оптимизатором двух функций).
Фреймы в стеке вызовов почти всегда верные, но при условии наличия символов для всех фреймов. Фреймы в стеке вызовов могут оказаться некорректными при повреждении стека, при наличии функций на ассемблере, или в фреймах операционной системы при отсутствии соответствующих символов в стеке вызовов.
Глобальные и статические переменные всегда отображаются правильно. Это же относится к структурным типам. Если существует указатель на структуру и его значение правильно, каждая переменная-элемент структуры имеет правильное значение.
В связи с этими ограничениями следует по возможности отлаживать неоптимизированные версии программы. По умолчанию оптимизация отключена в конфигурации отладки программы C++ и включена в конфигурации выпуска.
Тем не менее, ошибка может появиться только в оптимизированной версии программы. В этом случае отлаживать нужно как раз оптимизированный код.
Включение оптимизации в конфигурации построения отладки
При создании нового проекта выберите в качестве конечного продукта Win32 Debug . Используйте Win32 Debug , пока программа не будет полностью отлажена и готова к созданию сборки Win32 Release . Компилятор не оптимизирует Win32 Debug .
Выберите проект в обозревателе решений.
В окне папок слева выберите папку C/C++ .
В папке C++ выберите элемент Optimization .
В списке свойств справа найдите Optimization . Параметр этого свойства скорее всего будет Disabled ( /Od ) . Выберите один из параметров ( Minimum Size``( /O1 ) , Maximum Speed``( /O2 ) , Full Optimization``( /Ox ) или Custom ).
Если для свойства Custom выбран параметр Optimization , это означает, что можно устанавливать параметры для любого из остальных свойств, показанных в списке.
Выберите "Свойства конфигурации", "C/C++", узел "Командная строка" страницы свойств проекта и добавьте ( /Zo ) в текстовое поле Дополнительные параметры.
Для использования /Zo требуется Visual Studio 2013 с обновлением 3 или более поздняя версия.
Добавление параметра /Zo приведет к отключению режима Изменить и продолжить.
При отладке оптимизированного кода перейдите в окно Дизассемблированный код, чтобы просмотреть, какие инструкции в действительности создаются и выполняются. При задании точек останова следует знать, что они могут двигаться вместе с инструкцией. Рассмотрим следующий пример кода:
Допустим, точка останова установлена на этой строке. Можно ожидать, что точка останова будет пройдена 10 раз. Но если код оптимизирован, она будет пройдена всего один раз. Это связано с тем, что первая инструкция задает для x значение 0. Компилятор распознает, что конкретная инструкция должна быть выполнена один раз, и убирает ее из цикла. Точка останова перемещается вместе с ней. Инструкции, которые сравнивают и увеличивают x , остаются внутри цикла. При просмотре окна Дизассемблированный код для лучшего контроля размер шага автоматически равен одной инструкции, что бывает полезно при пошаговом прохождении оптимизированного кода.
Надо сделать так, чтобы ошибки операции возникали раньше mParamStack.pop_back();
В дебаге они и возникают раньше, а в релизе сначала идет pop, после которого присвоение без промежуточной переменной.
Сразу поставил, не прокатило.
Пока так:
Ого. И так не работает!
При делении на 0 pop_back все равно выполняется.
Попробуй еще так.
должно сбросить предсказатель ветвлений
Странно. Номально volatile работает:
Без volatile да, func() выполняется до исключения.
С goto не получилось. Атрибут тоже не навешивается (наверно из-за того, что все в шаблонах).
Минимальный код того, что у меня происходит.
По идее это не должно работать правильно. И в этом минимальном коде система throw работает неправильно, т. е. catch ничего не ловит, а просто падает (terminate called after throwing an instance of 'int').
В проекте ловит правильно, но возле деления на 0 возникают проблемы с поста №0.
Chipmunk
> Минимальный код того, что у меня происходит.
И не стрёмно тебе бросаться исключениями в хендлере сигнала?
RPGman
> И не стрёмно тебе бросаться исключениями в хендлере сигнала?
я написал, что
> По идее это не должно работать правильно.
> я написал, что
> > По идее это не должно работать правильно.
А зачем тогда это было писать? Уводишь в сторону от проблемы?
> В проекте ловит правильно
Исключительный случай, который перестанет работать при смене фазы луны.
это не оптимизация
по стандарту, C++ не поддерживает арифметические исключения, которые, к тому же, могут приходить от процессора асинхронно
Chipmunk
> нужно в хендлере обезопасить вектор
Обезопасить вектор это как?
Не проще ли тупо back() проверить на ноль?
RPGman
> Обезопасить вектор это как?
Ни малейшего понятия.
> Не проще ли тупо back() проверить на ноль?
Нельзя, это универсальный класс. Он обрабатывает только свои проблемы типа stack underflow. А в стеке лежат элементы юзера, т. е. может ему и надо делить на 0 (та и вообще, что такое 0 для какого-то его типа?).
И вот этот велосипед для примера инстанциируется интами и делится на 0.
А дальше ты знаешь. (с)
Для того чтобы во время выполнения программы по шагам иметь возможность контролировать значение переменной, нужно добавить имя этой переменной в список наблюдаемых элементов (Watch List). Для этого надо из меню Run выбрать команду Add Watch (Добавить наблюдаемый элемент). После этого появится диалоговое окно Watch Properties (рис. 12).
В поле Expression появившегося диалогового окна Watch Properties нужно ввести имя переменной. Можно просматривать значения не только переменных, но и выражений типа х*(y+z). Единственное ограничение - выражение не может содержать вызовов функций. Допускается также просмотр значений записей, массивов и других структурированных элементов.
|
Рис. 12. Добавление имени переменной в список Watch List.
Поле Repeat Count используется в том случае, если нужно просмотреть часть большого массива. Предположим, что вам надо знать значения элементов 826-833 следующего массива
BigArray: array[1..1000] of Integer;
Тогда в поле Expression указываем значение BigArray [826] и устанавливаем параметр Repeat Count равным 8. При этом вам будут показаны значения восьми элементов массива— от 826 по 833.
Использование поля Digits позволяет определить количество значащих цифр при выводе числа с плавающей точкой.
Отключенная опция Enabled предотвращает вывод значения переменной, однако, среда будет хранить все параметры, заданные для ее просмотра. Так можно временно убрать с экрана информацию о переменной, которая в настоящий момент вам не нужна, и быстро восстановить ее на экране при необходимости без повторного ввода характеристик просмотра.
В диалоговом окне имеется также набор переключателей для выбора способа представления переменной. Значение Defaultпозволяет среде разобраться с типом переменной самостоятельно. Как правило, такое решение оптимально, однако в любой момент вы можете представить переменную как переменную того типа, который вас интересует. Опция Memory dump представляет информацию как набор байтов, что бывает полезно, когда необходимо увидеть внутреннее представление информации в переменной.
Рис. 13. Результат добавления имени переменной в список Watch List.
· Variable 'X' inaccessible here due to optimization (Переменная 'X' недоступна из-за оптимизации). В этой точке значение переменной просмотреть невозможно (иногда это можно сделать в другом месте программы), так как для нее не выделена память из-за оптимизации программы компилятором.
· Symbol was eliminated by linker (Переменная удалена компоновщиком). Переменная удалена из кода программы компоновщиком, так как на нее нет ни одной ссылки в тексте программы.
В качестве примера на рис. 14 приведен вид окна редактора кода и окна Watch List во время пошагового выполнения программы.
Рис. 14. Контроль значений переменных во время пошагового выполнения программы.
В окне Редактора кода стрелкой помечена инструкция, которая будет выполнена на следующем шаге выполнения программы (при нажатии клавиши F8 или при выборе команды Step Over из меню Run), в диалоговом окне Watch List выведены значения переменных.
Существует еще один способ, позволяющий проверить значение переменной, не добавляя ее имя в список Watch List. Заключается он в следующем. После того как программа достигнет точки останова, в результате чего откроется окно редактора кода, нужно установить курсор мыши на имени переменной, значение которой надо проверить. В окне редактора кода появится окно подсказки, в котором будет выведено значение переменной (рис. 15).
Рис. 15. Контроль значения переменной без добавления имени в список Watch List.
Читайте также: