Как помешать g ++ оптимизировать цикл, управляемый переменной, которая может быть изменена IRQ? - PullRequest
21 голосов
/ 29 февраля 2012

Рассмотрим следующий фрагмент кода:

unsigned global;
while(global);

global модифицируется в функции, которая вызывается IRQ. Однако g ++ удаляет тест «не равен нулю» и переводит цикл while в бесконечный цикл.

Отключение оптимизации компилятора решает проблему, но предлагает ли C ++ языковую конструкцию для этого?

Ответы [ 3 ]

17 голосов
/ 29 февраля 2012

Объявите переменную как volatile:

volatile unsigned global;

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

8 голосов
/ 29 февраля 2012

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

while(global)
  asm volatile("" : "+g"(global));

Это встроенный оператор сборки, который говорит, что он изменяет переменную (он передается как операнд ввода-вывода).Но он пуст, поэтому очевидно, что он ничего не делает во время выполнения.Тем не менее, оптимизатор считает, что он изменяет переменную - так сказали программисты, а компилятор, за исключением подстановки операндов (что означает простую замену одного текста другим), на самом деле не заботится о теле встроенной сборки и не выполняет никаких действий.забавные вещи к нему.

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

2 голосов
/ 29 февраля 2012

Вы можете использовать атрибуты GCC в объявлении функции, чтобы отключить оптимизацию для каждой функции:

void myfunc() __attribute__((optimize(0)));

Подробнее см. На странице Атрибуты функции GCC .

...