Какие флаги компиляции следует использовать, чтобы избежать ошибок времени выполнения

Только что узнал здесь, что -Wsequence-point флаг компиляции выдает предупреждение, когда код может вызывать UB. Я пробовал это с заявлением вроде

int x = 1;
int y = x+ ++x;

и это сработало очень хорошо. До сих пор я компилировал с gcc или g++ только с -ansi -pedantic -Wall. Есть ли у вас другие полезные флаги, чтобы сделать код более безопасным и надежным?


person CIsForCookies    schedule 14.05.2017    source источник
comment
@InternetAussie Но OP не об этом спрашивает.   -  person Sergey Kalinichenko    schedule 14.05.2017
comment
@dasblinkenlight Я думал, что это UB, и поскольку это UB, это не 2x + 1, по крайней мере, не по определению. Я ошибся?   -  person CIsForCookies    schedule 14.05.2017
comment
Вы пытались прочитать документацию gcc, чтобы узнать, какие флаги он поддерживает и какие из них будут вам полезны?   -  person Algirdas Preidžius    schedule 14.05.2017
comment
-ansi не делает ваш код более безопасным или надежным, он просто заставляет его использовать устаревшую версию диалекта. Используйте -std=<version> для соответствия выбранному вами стандарту, например -std=c99 или -std=c++11.   -  person spectras    schedule 14.05.2017
comment
@spectras Я использовал -ansi по историческим причинам. Новые флаги - это те, кому я хочу сделать свой код надежным.   -  person CIsForCookies    schedule 14.05.2017
comment
Почему бы вам не прочитать документацию по g ++? Здесь перечислены наиболее доступные флажки предупреждений.   -  person Jesper Juhl    schedule 14.05.2017
comment
@CIsForCookies Я думаю, его комментарий был предназначен для того, чтобы показать вам, как переписать код без UB.   -  person Sergey Kalinichenko    schedule 14.05.2017
comment
@dasblinkenlight о, спасибо :) Я начал сомневаться в своем понимании UB ...   -  person CIsForCookies    schedule 14.05.2017
comment
Связано: stackoverflow.com/a/11720263/3212865 (в основном OP спрашивает, как включить все предупреждения и ответ объясняет, почему такой вариант не существует и не имеет смысла, и вам решать, что является ошибкой в ​​вашем конкретном проекте, а что нет).   -  person spectras    schedule 14.05.2017
comment
@spectras thx! не видел этого. но все же мне интересно, какие флаги считаются хорошими и полезными, а какие просто завалиют меня бесполезными данными   -  person CIsForCookies    schedule 14.05.2017
comment
Для большинства практических целей -Wall более чем достаточно, иногда -Wextra. Кроме того, ручной выбор конкретных контекстно-зависимых предупреждений может иметь смысл. Рассмотрите также -Werror для сборки разработчика, если вы хотите применить политику отсутствия предупреждений.   -  person spectras    schedule 14.05.2017
comment
-pedantic -Wall -Wextra -Wconversion помогает вам, но не позволяет избежать ошибок времени выполнения, которых вы, вероятно, никогда не сможете достичь с помощью статического анализа кода.   -  person alk    schedule 14.05.2017
comment
@alk что ты имеешь в виду? сообщив мне, что операция с 'x' может быть неопределенной, я могу предположить, что моя ошибка времени выполнения была вызвана касанием строки x.   -  person CIsForCookies    schedule 14.05.2017
comment
Это флаги компилятора, которые я обычно использую с g++: -std=c++14 -O3 -ggdb3 -march=core2 -fno-common -pipe -Werror -Wall -Wextra -Wvla -Wreorder -Wnon-virtual-dtor -Wpacked -Wcast-align -Wenum-compare -Wpointer-arith -Wunused -Wuninitialized -Winit-self -Winvalid-pch -Woverlength-strings -Woverloaded-virtual -Woverflow -Wsequence-point -Wno-unknown-pragmas -Wtrigraphs -finput-charset=UTF-8 -Wpacked-bitfield-compat -Wlogical-op -Wsync-nand -Wstrict-null-sentinel -Wnoexcept   -  person Jesper Juhl    schedule 14.05.2017
comment
@JesperJuhl, у тебя там хорошая крышка! Разве некоторые из них не покрываются -Wall или -Wextra?   -  person Jonas    schedule 14.05.2017
comment
@Jonas Я так не верю. В противном случае я бы не добавил их явно ;-)   -  person Jesper Juhl    schedule 14.05.2017
comment
В общем случае ошибка времени выполнения относится к ошибке, возникающей во время ... ну: времени выполнения программы, а не во время компиляции (или времени компоновки). Поэтому, если вы столкнетесь с ошибкой компиляции или компоновки, вы никогда не столкнетесь с ошибкой времени выполнения, так как программа никогда не запустится, если вы столкнетесь с ошибкой компиляции или компоновки. :-)   -  person alk    schedule 14.05.2017
comment
Это, конечно, не остановит ошибку времени выполнения, но впоследствии это может быть лучшим индикатором, с которого я могу начать поиск ... это то, что я имел в виду. И это всего лишь предупреждение, поэтому у меня было бы предупреждение компилятора, которое могло бы превратиться в ошибку времени выполнения :)   -  person CIsForCookies    schedule 14.05.2017
comment
'+ nobugs' ........ :)   -  person ThingyWotsit    schedule 14.05.2017
comment
Некоторые бесценные вещи - Undefined Behavior Sanitizer (UBsan) и Address Sanitizer (Asan), доступные в виде плагинов для GCC и Clang. Они могут обнаруживать типы ошибок времени выполнения, такие как переполнение буфера / индексации, использование объектов до построения или после разрушения и т. Д., Которые не могут быть обнаружены предупреждениями во время компиляции. Почему они не могут? Что ж, выбирайте: код действителен до тех пор, пока он имеет допустимые входные данные, или он плохой, но стандарт не требует диагностики, или определение того, возникнет ли ошибка только из кода без его запуска, нетривиально ( что-то-что-то тормозит проблема что-то)   -  person underscore_d    schedule 15.05.2017


Ответы (1)


Как резюмировал alk, используйте эти флаги:

-pedantic -Wall -Wextra -Wconversion


Во-первых, я думаю, вы не хотите использовать флаг -ansi, как это предлагается в Что следует использовать в качестве флагов компилятора -ansi или явное -std = ...?

Во-вторых, -Wextra тоже кажется весьма полезным, как предлагается в -Wextra, насколько это действительно полезно?

В-третьих, -Wconversion также кажется полезным, как предлагается в Могу ли я сделать так, чтобы GCC тоже предупреждал о прохождении от типов к функциям?

В-четвертых, также помогает -pedantic, поскольку предложено в Какова цель использования -pedantic в компиляторе GCC / G ++?.

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

Пример с gcc:

Georgioss-MacBook-Pro:~ gsamaras$ cat main.c 
int main(void)
{
    int x = 1;
    int y = x+ ++x;
    return 0;
}
Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
main.c:4:16: warning: unsequenced modification and access to 'x' [-Wunsequenced]
    int y = x+ ++x;
            ~  ^
main.c:4:9: warning: unused variable 'y' [-Wunused-variable]
    int y = x+ ++x;
        ^
2 warnings generated.
Georgioss-MacBook-Pro:~ gsamaras$ gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.38)
Target: x86_64-apple-darwin16.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

Пример с g ++, та же версия:

Georgioss-MacBook-Pro:~ gsamaras$ cp main.c main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp 
main.cpp:4:16: warning: unsequenced modification and access to 'x'
      [-Wunsequenced]
    int y = x+ ++x;
            ~  ^
main.cpp:4:9: warning: unused variable 'y' [-Wunused-variable]
    int y = x+ ++x;
        ^
2 warnings generated.

Соответствующий мой ответ, что Стена снова спасает положение с аналогичной проблемой.

person gsamaras    schedule 14.05.2017
comment
Примечание: -Wall не включает все предупреждения - это далеко не так. Лично я всегда добавляю как минимум -Wextra. Но даже это по-прежнему не включает все полезные предупреждения, есть много других, которые вы можете включить. - person Jesper Juhl; 14.05.2017
comment
@JesperJuhl Нет ли чего-то похожего на FAQ по флагам компилятора из gcc? Мне кажется, это довольно распространенная проблема конфигурации ... - person SebNag; 14.05.2017