Практическое руководство. Отладка оптимизированного кода
Примечание
Отображаемые диалоговые окна и команды меню могут отличаться от описанных в справке в зависимости от текущих параметров или выпуска.Чтобы изменить параметры, в меню "Сервис" выберите команду "Импорт и экспорт параметров".Для получения дополнительной информации см. Настройка параметров разработки в Visual Studio.
Примечание
Параметр компилятора /Zo (улучшение оптимизированного процесса отладки) (впервые появившийся в Visual Studio с обновлением 3) генерирует расширенные сведения по отладке для оптимизированного кода (проекты, которые не были собраны с параметром компилятора /Od.См. раздел Параметры /O (оптимизация кода)).Это обеспечивает улучшенную поддержку отладки локальных переменных и встроенных функций.
Когда используется параметр компилятора /Zo, режим Изменить и продолжить отключается.
Когда компилятор оптимизирует код, он перераспределяет и реорганизует инструкции. Это приводит к повышению эффективности скомпилированного кода. В связи с этим перераспределением отладчик не всегда может идентифицировать исходный код, соответствующий набору инструкций.
Оптимизация может повлиять на:
Локальные переменные (могут быть удалены оптимизатором или перемещены в места, недоступные для отладки).
Код внутри функций (изменяется расположение при слиянии оптимизатором блоков кода).
Имена функций в фреймах стека вызовов (могут оказаться некорректными при слиянии оптимизатором двух функций).
Фреймы в стеке вызовов почти всегда верные, но при условии наличия символов для всех фреймов. Фреймы в стеке вызовов могут оказаться некорректными при повреждении стека, при наличии функций на ассемблере, или в фреймах операционной системы при отсутствии соответствующих символов в стеке вызовов.
Глобальные и статические переменные всегда отображаются правильно. Это же относится к структурным типам. Если существует указатель на структуру и его значение правильно, каждая переменная-элемент структуры имеет правильное значение.
В связи с этими ограничениями следует по возможности отлаживать неоптимизированные версии программы. По умолчанию оптимизация выключена в конфигурации отладки программы Visual C++ и включена в конфигурации выпуска.
Тем не менее, ошибка может появиться только в оптимизированной версии программы. В этом случае отлаживать нужно как раз оптимизированный код.
Включение оптимизации в конфигурации построения отладки
При создании нового проекта выберите в качестве конечного продукта Win32 Debug. Используйте Win32Debug, пока программа не будет полностью отлажена и готова к созданию сборки Win32 Release. Компилятор не оптимизирует Win32 Debug.
Выберите проект в обозревателе решений.
В меню Вид выберите команду Страницы свойств.
В диалоговом окне Страницы свойств убедитесь, что в раскрывающемся списке Конфигурация выбран пункт 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 приведет к отключению режима Изменить и продолжить.
При отладке оптимизированного кода перейдите в окно Дизассемблирование, чтобы просмотреть, какие инструкции в действительности создаются и выполняются. При задании точек останова следует знать, что они могут двигаться вместе с инструкцией. Рассмотрим следующий пример кода:
for (x=0; x<10; x++)
Допустим, точка останова установлена на этой строке. Можно ожидать, что точка останова будет пройдена 10 раз. Но если код оптимизирован, она будет пройдена всего один раз. Это связано с тем, что первая инструкция задает для x значение 0. Компилятор распознает, что конкретная инструкция должна быть выполнена один раз, и убирает ее из цикла. Точка останова перемещается вместе с ней. Инструкции, которые сравнивают и увеличивают x, остаются внутри цикла. При просмотре окна Дизассемблирование для лучшего контроля размер шага автоматически равен одной инструкции, что бывает полезно при пошаговом прохождении оптимизированного кода.