Использование volatile квалификатора подавляет предупреждение компилятора - PullRequest
0 голосов
/ 16 ноября 2018

Сегодня я просматривал код парня, в котором он объявил переменную volatile.На вопрос об этом он сказал, что в некоторых системах это вызывает странное поведение.

При удалении volatile и компиляции он выдавал это предупреждение компилятора

iteration 2 invokes undefined behavior [-Waggressive-loop-optimizations]

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

int a[4]={1,2,3,4};
int i;   //when declared volatile int i, doesn't produce warning
i=0;
while(i<5) {
    printf("%d\t", a[i]);    //a[4] will invoke undefined behavior
    i+=2;   
}

Теперь я не могу понять две вещи:

  1. Какие именно флаги gcc я должен включить, чтобы получить это предупреждение?
  2. Почему объявление i как volatile подавляет это предупреждение?

Ответы [ 3 ]

0 голосов
/ 16 ноября 2018

Неопределенное поведение, которое у вас есть, заключается в том, что ваш цикл допускает i = 4, что будет считываться после конца массива.Это замечает оптимизатор цикла, но, конечно, это проблема независимо от оптимизации.

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

Использование volatile исключительно для обхода предупреждения - ужасная практика.Вместо этого измените условие while на while (i < 4).

0 голосов
/ 16 ноября 2018

Когда агрессивная оптимизация цикла видит следующий код ...

int i;
i=0;
while(i<5) {
    printf("%d\t", a[i]);
    i+=2;   
}

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

printf("%d\t", a[0]);
printf("%d\t", a[2]);
printf("%d\t", a[4]);

Проблема! Итерации 0 и 1 хороши, но итерация 2 будет выполнять доступ к массиву за пределами границ, вызывая неопределенное поведение. Вот почему вы получили предупреждение, которое вы сделали.

Объявление i значением volatile не позволяет компилятору выполнить эту оптимизацию (поскольку он не может быть уверен, что другой процесс не изменяет значение i во время выполнения цикла), поэтому он должен выйти код, как это было. У вас все еще есть неопределенное поведение, просто компилятор не предупреждает вас об этом. В общем, ужасное «исправление» от вашего коллеги.

0 голосов
/ 16 ноября 2018
  1. В предупреждении указывается, какой флаг разрешает его: -Waggressive-loop-optimizations
  2. Объявление переменной volatile означает, что компилятор должен предположить, что вещи вне контроля компилятора могут проверять и изменять переменную. Поэтому нельзя предположить, что i когда-либо примет значение 4 (или что i += 2 всегда добавит 2 к значению i и т. Д.).
...