2

Почему необходимо/рекомендуется отключать все оптимизации компилятора при отладке приложения?Что случилось, если оптимизация компилятора включена в отладочной сборке?

фона

Я работал в 8-разрядном микроконтроллере (OKI 411), который имеет 15K полезного пространства памяти для кода обслуживания прерываний + ПЗУ области/окно (константный глобальные переменных) + кода. Мы почти съели ~ 13K, поэтому очень заманчиво включить максимально возможную оптимизацию во время даже отладки.

ответ

6

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

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

1

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

Кроме этого, проблем не должно быть.

2

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

В вашем случае я обязательно включил его.

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

5

Рассмотрим:

for (i = 0; i < 10; i++) { 
    src[i] = dest[i]; 
} 

После оптимизации этот код может выглядеть следующим образом:

src[0] = dest[0]; 
src[1] = dest[1]; 
⋮ 
src[9] = dest[9]; 

Другими словами, нет никакого i больше. Отладчик ожидал бы, что i будет на фрейме стека, но оптимизатор удалил его.

Кроме того, при пошаговом режиме ПК будет прыгать повсюду (по-видимому, случайным образом), и вы столкнетесь с другой другой странностью, которая сделает отладку очень сложной или невозможной (в зависимости от того, что сделал оптимизатор).

2

Я столкнулся с аналогичной ситуацией, когда я пытался прочитать из реестра аппаратных средств, регистр был отображен в память, и это дало мне неправильные значения с CFLAGS = "- o2" в gcc.However, когда я повернул CFLAGS = "- O0", он начал работать. Может быть, стоит упомянуть, что тот же результат может быть достигнут путем включения его в изменчивую переменную, поэтому оптимизация компилятора обойдется.