Поделиться через


Оптимизированный код для отладки

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

Лучший интерфейс доступен начиная с Visual Studio 2022 версии 17.14, который позволяет отлаживать оптимизированный код, как если бы он был скомпилирован неоптимизирован, сохраняя скорость оптимизированного кода. Дополнительные сведения см. в динамической отладке C++ (предварительная версия).

Примечание.

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

Примечание.

Параметр компилятора /Zo (улучшенная отладка для оптимизированного кода), появившийся в Visual Studio Update 3, создаёт более подробные сведения об отладке для оптимизированного кода проектов, которые не созданы с параметром компилятора /Od. Смотрите /O Опции (Оптимизация кода). Это включает улучшенную поддержку отладки локальных переменных и встроенных функций.

Редактировать и Продолжить отключено при использовании параметра компилятора /Zo.

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

Оптимизация может повлиять:

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

  • Позиции внутри функции, которые изменяются при слиянии блоков кода оптимизатором.

  • Имена функций для кадров в стеке вызовов, возможно, будут неправильными, если оптимизатор объединяет две функции.

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

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

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

    Однако ошибка может отображаться только в оптимизированной версии программы. В этом случае необходимо выполнить отладку оптимизированного кода.

Включение оптимизации в конфигурации отладочной сборки

  1. При создании проекта выберите целевой объект Win32 Debug. Используйте целевой объект Win32 Debug до полной отладки программы, и вы будете готовы создать целевой объект Win32 Release. Компилятор не оптимизирует целевой объект Win32 Debug.

  2. Выберите проект в обозревателе решений.

  3. В меню Представления щелкните Страницы Свойств.

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

  5. В представлении папок слева выберите папку C/C++.

  6. В папке C++ выберите Optimization.

  7. В списке свойств справа найдите Optimization. Настройка рядом с ним, вероятно, указана как Disabled (/Od). Выберите один из других вариантов (Minimum Size``(/O1), Maximum Speed``(/O2), Full Optimization``(/Ox)или Custom).

  8. Если выбран параметр Custom для Optimization, теперь можно задать параметры для любого из других свойств, отображаемых в списке свойств.

  9. Выберите узел "Свойства конфигурации", C/C++, узел "Командная строка" на странице свойств проекта и добавьте (/Zo) в текстовое поле "Дополнительные параметры".

    Предупреждение

    Добавление /Zo отключает редактирование и продолжение .

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

for (x=0; x<10; x++)

Предположим, что вы устанавливаете точку останова в этой строке. Вы можете ожидать, что точка останова будет достигнута 10 раз, но если код оптимизирован, точка останова достигается только один раз. Это связано с тем, что первая инструкция задает x значение 0. Компилятор распознает, что это нужно сделать только один раз и перемещает его из цикла. Точка останова перемещается вместе с ней. Инструкции, которые сравнивают и увеличивают x, остаются внутри цикла. При просмотре окна дизассемблирования единица шага автоматически устанавливается на инструкцию для большего контроля, что полезно при пошаговом переходе по оптимизированному коду.