Неинициализированные предупреждения о необходимости -O2 - PullRequest
3 голосов
/ 09 мая 2019

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

unsigned long fac(unsigned long n)
{
  unsigned long product;

  while (n > 1)
  {
    product = product * n;
    n = n - 1;
  }

  return product;
}

➜  a g++ --version
g++ (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)

edit: Чтобы прояснить вопрос, я, конечно, включил предупреждение.

Ответы [ 3 ]

4 голосов
/ 09 мая 2019

Предупреждение появляется в режиме -O2 (или любой другой оптимизации) вместе с включенной опцией -Wmaybe-uninitialized. Опция -Wmaybe-uninitialized также включена с -Wall и с любым из включенных режимов оптимизации.

Причина этого согласно документации GCC :

-Wmaybe-uninitialized

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

Затем следует пример того, как может произойти вышеупомянутый сценарий.

1 голос
/ 09 мая 2019

Чтобы ответить на вопрос почему чуть более подробно, это делается главным образом для уменьшения количества ложных срабатываний и времени компиляции.Пропуск, выдающий эти предупреждения (вариант -Wmaybe-uninitialized), выполняется очень поздно в конвейере компиляции (см. gcc/passes.def; соответствующий пропуск pass_late_warn_uninitialized находится на строке 338 или около того).GCC изо всех сил старается создать как можно меньше ложных срабатываний для этого предупреждения.Для этого ему нужна более точная информация о программе.Чтобы получить эту информацию, необходимо предварительно выполнить некоторые анализы / преобразования (например, переход по потокам особенно полезен).И некоторые из них слишком дороги, чтобы их можно было включить на -O0.

Разработка GCC выполняется в открытом доступе.Все основные решения обычно обсуждаются в списках рассылки и в bugzilla.См., Например, этот комментарий .


0 голосов
/ 09 мая 2019

Неинициализированная переменная не является технической ошибкой;Память в сборке x86 / x64 может быть неинициализирована.Чтение из неинициализированной памяти (которая читается с помощью ограничений защищенного / длинного режима) допустимо.Вы получите неопределенные значения, но технически действительные.

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

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