Флаг компилятора -O0 имеет тот же эффект, что и ключевое слово volatile в C? - PullRequest
0 голосов
/ 15 мая 2018

Когда вы используете флаг компилятора -O0 в C, вы указываете компилятору избегать любого вида оптимизации.Когда вы определяете переменную как volatile, вы указываете компилятору избегать оптимизации этой переменной.Можем ли мы использовать два подхода взаимозаменяемо?И если да, каковы плюсы и минусы?Ниже приведены некоторые плюсы и минусы, которые я могу придумать.Есть ли еще?

Плюсы:

  • Использование флага -O0 полезно, если у нас есть большая база кода внутри которойпеременные, которые должны были быть объявлены как volatile, не являются.Если код показывает ошибочное поведение, вместо того, чтобы идти в коде и находить, какие переменные необходимо объявить как volatile, мы можем просто использовать флаг -O0 , чтобы исключить вероятность того, что оптимизация вызывает проблему.

Минусы:

  • Флаг -O0 влияет на весь код, в то время как ключевое слово volatile влияет только наконкретная переменная.Например, если мы работаем над небольшим микроконтроллером, это может быть проблемой, поскольку использование -O0 может привести к большому исполняемому файлу.

Ответы [ 4 ]

0 голосов
/ 16 мая 2018

Существующие ответы уже достаточно хорошо охватывают volatile, но я считаю, что основная причина этого вопроса не имеет ничего общего с volatile.

Если ваш код работает с -O0, но не с включенной оптимизацией, у вас может быть множество ошибок в коде, или также возможно, что компилятор содержит ошибки. Будучи помеченным как «микроконтроллер», я не исключаю ошибок компилятора.

Возможно, что у вас переполнение или переполнение буфера, например, и оптимизатор просто упорядочивает ваш код немного другим способом, который выявляет ошибку. Попробуйте запустить свой код через статический анализатор кода (такой как cppcheck или статический анализ кода llvm). Однако будет ли это возможным, зависит от того, насколько специфичен микроконтроллер для вашего кода.

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

0 голосов
/ 15 мая 2018

Использование флага -O0 полезно, если у нас есть большая база кода, внутри которой переменные, которые должны были быть объявлены как volatile, не являются

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

Если код показывает некорректное поведение, вместо того, чтобы идти в коде и находить, какие переменные должны быть объявлены как volatile, мыможно просто использовать флаг -O0, чтобы исключить вероятность того, что оптимизация вызывает проблему.

Это неверный вывод.Нет гарантии, что O0 "исправит" проблему из-за отсутствия переменной (ей) volatile квалификатор.Проблема все еще существует в вашем коде и должна быть исправлена.

Вы, похоже, неправильно поняли volatile.Это не то, что контролирует оптимизацию компилятора как таковую.Принимая во внимание, что O0 обычно отключает большинство оптимизаций (хотя компилятор может все же оптимизировать).

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

Нет причин отключать оптимизацию компилятора.Вам нужно исправить проблему в своем коде, то есть добавить квалификаторы volatile в переменную (и), которые в ней нуждаются.

0 голосов
/ 15 мая 2018

Краткий ответ: ключевое слово volatile означает , а не означает "не оптимизировать".Это нечто совершенно другое.Он сообщает компилятору, что переменная может быть изменена чем-то, что не видно компилятору в обычном потоке программы.Например:

  1. Может быть изменено аппаратно - обычно регистры отображаются в адресном пространстве памяти
  2. Может быть изменено функцией, которая никогда не вызывается - например, подпрограмма прерывания
  3. Переменная может быть изменена другим процессом или оборудованием - например, совместно используемой памятью в многопроцессорных / многоядерных системах

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

Здесь у вас есть пример:

int foo(volatile int z)
{
    return z + z + z + z;
}

int foo1(int z)
{
    return z + z + z + z;    
}

и полученный код (опция оптимизации -O0)

foo(int):
  push rbp
  mov rbp, rsp
  mov DWORD PTR [rbp-4], edi
  mov edx, DWORD PTR [rbp-4]
  mov eax, DWORD PTR [rbp-4]
  add edx, eax
  mov eax, DWORD PTR [rbp-4]
  add edx, eax
  mov eax, DWORD PTR [rbp-4]
  add eax, edx
  pop rbp
  ret
foo1(int):
  push rbp
  mov rbp, rsp
  mov DWORD PTR [rbp-4], edi
  mov eax, DWORD PTR [rbp-4]
  sal eax, 2
  pop rbp
  ret

Разница очевидна, я думаю.Переменная volatile читается 4 раза, а volatile читается один раз, затем умножается на 4.

Вы можете играть здесь: https://godbolt.org/g/RiTU4g

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

Имейте в виду, что "volatile" не означает или не гарантирует целостность и атомарность .

0 голосов
/ 15 мая 2018

Флаг компилятора -O0 ни в коем случае не является заменой для правильного использования volatile, потому что код, который не работает, когда он должным образом оптимизирован компилятором, по своей сути нарушен.Вы не хотите, чтобы неработающий код давал вам вид «работающего», пока кто-то не забудет бросить переключатель -O0.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...