철저하고 자세한 g ++ 경고를 활성화하는 플래그


122

종종 C 아래 gcc에서 다음과 같은 경고 플래그 세트로 시작합니다 (여러 소스에서 고통스럽게 조립 됨).

-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi

이 경고 세트로 (적어도 내 디버그 버전) 빌드하고 가능한 모든 것 (일반적으로 모든 것)을 수정 한 다음 관련성이 없거나 수정할 수없는 경우에만 플래그를 제거합니다 (거의 경우). 때로는 -Werror컴파일하는 동안 물러나야하는 경우 도 추가 합니다.

저는 C ++을 선택하고 있습니다 (예, 저는 15 년 뒤입니다). 바로 시작하고 싶습니다.

내 질문은 : 누군가가 C ++에 대해 미리 컴파일 된 유사한 완전한 경고 플래그 세트를 가지고 g++있습니까? (나는 그들 중 많은 것이 동일 할 것이라는 것을 알고 있습니다.)


69
무엇 (이 노골적으로 결정 이후 GCC의 요구 거짓말 에 대한 것은 -Wall)가있다 -Wbloody_everything플래그 :-)
paxdiablo

질문을 속임수로 표시 할 수 있지만 실제로 질문에 답변했기 때문에 마지막 편집을 답변으로 넣을 수도 있습니다. 그리고 나는 그것을 그때 upvote를 기뻐할 것입니다 :)
ereOn

4
OP 및 @paxdiablo : GCC는 이러한 종류의 것을 일관되게 거부했지만 .NET을 통해 Clang에서 사용할 수 있습니다 -Weverything. Clang ++ 개발자조차도 사용자가이 기능을 켜는 것에 대해 약간 걱정하는 것을 읽었습니다. 분명히 내부 개발 용도로만 사용되었습니다. 그러나 이는 의미가 없습니다. 왜냐하면 전원을 켜는 -Weverything것이 이전에 알지 못했던 잠재적으로 유용한 경고를 발견하는 가장 좋은 방법 일 수 있기 때문 입니다.
Kyle Strand

1
OP 및 @paxdiablo 이제 주어진 GCC 버전에 대한 전체 경고 목록을 알아내는 방법이 있습니다. github.com/barro/compiler-warnings
Kyle Strand

답변:


138

나는 최대 수준의 경고를 받아야하는 최소한의 포함 세트를 찾았습니다. 그런 다음 목록에서 실제로 나쁜 일이 발생하고 있음을 나타내지 않거나 실제 빌드에 사용하기에는 너무 많은 오 탐지가 있다고 생각하는 일련의 경고를 제거했습니다. 내가 제외시킨 각 항목이 제외 된 이유에 대해 언급했습니다. 이것이 제가 제안한 마지막 경고입니다.

-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused

존재하는 의심스러운 경고 :

  • -Wno-unused나중에 사용할 것으로 알고 있지만 아직 작성된 기능이없는 변수가 종종 있기 때문에 포함 합니다. 그것에 대한 경고를 제거하면 때때로 사물의 구현을 연기하는 선호하는 스타일로 작성할 수 있습니다. 균열을 통해 미끄러지는 것이 없는지 확인하기 위해 가끔씩 끄는 것이 유용합니다.

  • -Wdisabled-optimization강력한 사용자 선호 설정 인 것 같습니다. 나는 방금 이것을 내 빌드에 추가했고 (분명한 이유로 최적화 된 빌드에만) 아무것도 나타나지 않았으므로 적어도 내가 코딩하는 방식에 대해서는 특별히 수다스러운 경고가 아닌 것 같습니다. 이 경고를 유발하는 코드가 반드시 잘못된 것은 아니지만 도구를 사용하는 대신 도구를 사용한다고 믿기 때문에 포함합니다. gcc가 내가 작성한 방식으로 코드를 최적화 할 수 없다고 말하면 다시 작성해야합니다. 나는이 경고를 유발하는 코드가 더 모듈화 된 것으로부터 이익을 얻을 수 있다고 생각합니다.

  • -Wfloat-equal안전한 동등성 비교 (특히 계산되지 않은 값 -1과의 비교)에 대해 경고합니다. 이것을 사용하는 코드의 예는 float 벡터가 있다는 것입니다. 이 벡터를 살펴보면 아직 평가할 수없는 몇 가지 요소가 있으므로 -1.0f로 설정합니다 (내 문제는 양수 만 사용하므로 -1은 도메인 외부에 있음). 나중에 -1.0f 값을 업데이트합니다. 다른 작동 방법에 쉽게 적합하지 않습니다. 나는 대부분의 사람들 이이 문제를 가지고 있지 않다고 생각하고 부동 소수점에서 정확한 숫자를 비교하는 것은 아마도 오류 일 것이므로 기본 목록에 포함하고 있습니다.

  • -Wold-style-cast내가 사용하는 라이브러리 코드에 많은 오 탐지가 있습니다. 특히 네트워킹에 사용되는 htonl 함수 제품군과 내가 사용중인 Rijndael (AES) 암호화 구현에는 경고하는 구식 캐스트가 있습니다. 이 두 가지를 모두 교체하려고하지만 내 코드에 불평 할만한 다른 것이 있는지 확실하지 않습니다. 하지만 대부분의 사용자는이 기능을 기본적으로 설정해야합니다.

  • -Wsign-conversion힘든 일이었습니다 (그리고 거의 목록을 만들지 않았습니다). 내 코드에서 켜면 엄청난 양의 경고 (100 개 이상)가 생성되었습니다. 거의 모든 사람들이 결백했습니다. 그러나 나는 확실하지 않은 곳에서는 부호있는 정수를 사용하는 데주의를 기울 였지만, 특정 문제 영역의 경우 일반적으로 많은 양의 정수 나누기 때문에 부호없는 값을 사용하여 약간의 효율성 증가를 얻었습니다. 실수로 부호있는 정수를 부호없는 정수로 승격 한 다음 나누는 것에 대해 염려했기 때문에이 효율성을 희생했습니다 (더하기, 빼기 및 곱하기와 달리 안전하지 않음). 이 경고를 켜면 대부분의 변수를 서명되지 않은 유형으로 안전하게 변경하고 다른 위치에 몇 가지 캐스트를 추가 할 수있었습니다. 경고가 그렇게 똑똑하지 않기 때문에 현재 사용하기가 조금 어렵습니다. 예를 들어unsigned short + (integral constant expression), 그 결과는 암시 적으로 int로 승격됩니다. 그런 다음 해당 값을 unsigned또는에 할당하면 unsigned short안전하더라도 잠재적 인 기호 문제에 대해 경고 합니다. 이것은 거의 모든 사용자에게 가장 선택적인 경고입니다.

  • -Wsign-promo: 참조 -Wsign-conversion.

  • -Wswitch-default무의미 ​​해 보입니다 (모든 가능성을 명시 적으로 열거했다면 항상 기본 케이스를 원하지는 않습니다). 그러나이 경고를 켜면 아마도 좋은 생각이 될 수 있습니다. 나열된 가능성을 제외한 모든 것을 명시 적으로 무시하려는 경우 (다른 숫자도 가능) 다음을 입력하십시오.default: break;명시 적으로 만들 수 있습니다. 모든 가능성을 명시 적으로 열거하는 경우이 경고를 설정하면 실제로 가능한 모든 옵션을 다루 었는지 확인하기 위해 assert (false)와 같은 것을 입력하는 데 도움이됩니다. 문제의 영역이 무엇인지 명시하고 프로그래밍 방식으로 적용 할 수 있습니다. 그러나 모든 곳에서 assert (false)를 고수 할 때는주의해야합니다. 기본 케이스로 아무것도하지 않는 것보다 낫지 만 어설 션은 평소와 같이 릴리스 빌드에서는 작동하지 않습니다. 즉, 네트워크 연결이나 절대적으로 제어 할 수없는 데이터베이스에서 가져온 번호의 유효성을 검사하는 데 신뢰할 수 없습니다. 예외 또는 일찍 반환하는 것이이를 처리하는 가장 좋은 방법입니다 (하지만 여전히 기본 케이스가 있어야합니다!).

  • -Werror나에게 중요한 것입니다. 다중 대상이있는 다중 스레드 빌드에서 많은 양의 코드를 컴파일 할 때 경고가 발생하기 쉽습니다. 경고를 오류로 바꾸면 경고를 알아 차릴 수 있습니다.

그런 다음 유용하다고 생각하지 않았기 때문에 위 목록에 포함되지 않은 경고 집합이 있습니다. 다음은 기본 목록에 포함하지 않는 이유에 대한 경고 및 내 의견입니다.

없는 경고 :

  • -Wabi다른 컴파일러의 바이너리를 결합하지 않기 때문에 필요하지 않습니다. 어쨌든 컴파일을 시도했지만 트리거되지 않았으므로 불필요하게 장황 해 보이지 않습니다.

  • -Waggregate-return내가 오류라고 생각하는 것이 아닙니다. 예를 들어, 클래스 벡터에서 범위 기반 for 루프를 사용할 때 트리거됩니다. 반환 값 최적화는 이것의 모든 부정적인 영향을 처리해야합니다.

  • -Wconversion이 코드에서 트리거 : short n = 0; n += 2;int 로의 암시 적 변환은 대상 유형으로 다시 변환 될 때 경고를 발생시킵니다.

  • -Weffc++이니셜 라이저 목록에서 모든 데이터 멤버가 초기화되지 않은 경우 경고를 포함합니다. 나는 의도적으로 많은 경우에 이것을하지 않기 때문에 경고 세트가 너무 복잡해서 유용하지 않다. 하지만 가끔씩 켜고 다른 경고 (예 : 기본 클래스의 비가 상 소멸자)를 검색하는 것이 좋습니다. 이것은 -Wall자체적으로 단일 경고 대신 경고 모음 (예 :)으로 더 유용합니다 .

  • -Winline헤더에서 함수를 인라인으로 정의하기 위해 최적화 목적으로 인라인 키워드를 사용하지 않기 때문에 부재합니다. 옵티마이 저가 실제로 그것을 인라인하는지 상관하지 않습니다. 이 경고는 클래스 본문에 선언 된 함수 (예 : 빈 가상 소멸자)를 인라인 할 수없는 경우에도 표시됩니다.

  • -Winvalid-pch 미리 컴파일 된 헤더를 사용하지 않기 때문에 누락되었습니다.

  • -Wmissing-format-attributegnu 확장을 사용하지 않기 때문에 사용되지 않습니다. 동일 -Wsuggest-attribute및 기타 여러

  • 그것의 부재로 인해 잠재적으로 주목할만한 것은 -Wno-long-long내가 필요하지 않은입니다. 정수 유형 을 포함하는 -std=c++0x( -std=c++11GCC 4.7에서)로 컴파일 long long합니다. C ++ 98 / C ++ 03에 갇힌 사람들은 경고 목록에서 제외를 추가하는 것을 고려할 수 있습니다.

  • -Wnormalized=nfc 이미 기본 옵션이며 최고로 보입니다.

  • -Wpadded클래스의 레이아웃을 최적화하기 위해 가끔 켜져 있지만 모든 클래스에 마지막 패딩을 제거 할 수있는 요소가 충분하지 않기 때문에 켜져 있지 않습니다. 이론적으로는 '무료'에 대한 추가 변수를 얻을 수 있지만이를 유지하기위한 추가 노력은 가치가 없습니다 (클래스 크기가 변경되면 이전에 사용 가능한 변수를 제거하기가 쉽지 않습니다).

  • -Wstack-protector 내가 사용하지 않기 때문에 사용되지 않습니다 -fstack-protector

  • -Wstrict-aliasing=3에 의해 켜져 -Wall있고 가장 정확하지만 레벨 1과 2가 더 많은 경고를 제공하는 것처럼 보입니다. 이론적으로 낮은 수준은 '더 강력한'경고이지만 더 많은 오탐을 초래합니다. 내 자신의 테스트 코드는 3 단계 모두에서 깔끔하게 컴파일되었습니다.

  • -Wswitch-enum내가 원하는 행동이 아닙니다. 모든 switch 문을 명시 적으로 처리하고 싶지 않습니다. 언어에 지정된 switch 문에서이를 활성화하는 메커니즘이있는 경우 유용 할 수 있지만 (열거 형에 대한 향후 변경 사항이 필요한 모든 곳에서 처리되도록 보장하기 위해) "all-or-nothing"설정에는 과잉입니다.

  • -Wunsafe-loop-optimizations잘못된 경고가 너무 많이 발생합니다. 이를 주기적으로 적용하고 결과를 수동으로 확인하는 것이 유용 할 수 있습니다. 예를 들어, 벡터의 모든 요소를 ​​반복하여 함수 집합을 적용 할 때 (범위 기반 for 루프 사용) 내 코드에서이 경고를 생성했습니다. 또한 const std :: string의 const 배열 생성자에 대한 경고입니다 (여기서는 사용자 코드에서 루프가 없음).

  • -Wzero-as-null-pointer-constant그리고 -Wuseless-cast내가 GCC 4.7로 전환 할 때 내가 추가 할 것 GCC-4.7-경고 만입니다.

이 연구의 결과로 gcc에 몇 가지 버그 보고서 / 향상 요청을 제출 했으므로 결국 "포함하지 않음"목록의 경고를 "포함"목록에 추가 할 수 있기를 바랍니다. . 이 목록에는이 스레드에서 언급 된 모든 경고가 포함되어 있습니다 (몇 가지 추가 사항 포함). 이 게시물에서 명시 적으로 언급하지 않은 많은 경고는 제가 언급하는 또 다른 경고의 일부로 포함되어 있습니다. 이 게시물에서 완전히 제외 된 경고를 발견 한 사람이 있으면 알려주십시오.

편집 : 내가 몇 가지를 놓친 것 같습니다 (지금 추가했습니다). 실제로 잘 숨겨져 있는 http://gcc.gnu.org에 두 번째 페이지 가 있습니다. 일반 경고 옵션C ++ 옵션 (경고를 보려면 아래로 스크롤)


최근에이 답변에 대한 내 연구를 기반으로 개선 요청을 제출했습니다 : gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . 경고 수준을 만들어 경고 상황을 극적으로 단순화합니다. 내 제안에 경고 내 제안 세트는 의미 -Winf을 만들 수있는 추가 제안, -Weverything 및-I-정말-평균이 -이 - 시간, 약 -W4입니다
데이비드 스톤

-Wpadded의 일부를 유발하는 개선 요청이 권장 목록에 추가되었습니다 : gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone

-Weffc ++의 일부가 권장 목록에 추가되도록하는 개선 요청 : gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone

1
@Predelnik : 그것보다 까다 롭습니다. -Wswitch-enum스위치의 모든 열거 값을 명시 적으로 처리하지 않으면 경고 default가 표시되고 명시 적으로 계산되지 않습니다. 반면에는 가능한 모든 값을 명시 적으로 다룬 경우에도 -Wswitch-default스위치에 default케이스 가없는 경우 경고 합니다.
David Stone

2
-isystem-I
BTW-

39

D' oh, 내 모든 원래 검색은 경고 를 억제 하는 방법에 대한 게시물의 99 %를 찾았지만 (무섭게도 충분히), 이 멋진 플래그 세트 (일부는 덜 관련성이 있음)가있는 이 댓글 을 보았습니다.

교차 확인 :

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g -O -Wall -Weffc++ -pedantic  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline \
-Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings

그래서 좋은 출발점이라고 생각합니다. 이것이 속임수라는 사실은 몰랐지만 적어도 깊이 묻혔습니다. :-)


1
아마도 그것은 버전 사이에 변경되는 것 같고, 태양 반점과 RMS의 변덕에 따라 변할 가능성이 있으므로 지나치게 노골적인 것은 아마도 아프지 않을 것입니다. 어쨌든 좋은 출발점입니다.
Sdaz MacSkibbons

3
'case OPT_W'에 대한 4.5.2의 c-opts.c / opts.c에 대한 빠른 grep에서 strict overflow, undef, strict nul sentinel, normalized, multichar, 암시 적 함수 선언, deprecated, endif 레이블, comment s , 내장 매크로 재정의,보다 큼, eq보다 큼, abi. 그들을 나열하는 명령 줄 옵션이 없다는 것은 미친 짓입니다.
Tony Delroy

3
-Wall기대했던 것을 하지 않는 것이 더 미친 것 같아요 . 하지만 감사합니다. 그중 일부는 매우 유용 해 보입니다!
Sdaz MacSkibbons

1
경고 비활성화는 그 자리가 있습니다. 결국 그들은 "경고"입니다. 또 다른 상황은 여러 경고를 활성화하는 플래그를 활성화했지만 이에 대해 선택하려는 경우입니다.
Tamás Szelei

1
어떻게 사용할 수 -Waggregate-return있습니까? 이 날의 모든 사용에 대한 경고 제공begin/end()
Flamefire

13

그중 일부는 이미 -Wall또는에 포함되어 -Wextra있습니다.

C의 좋은 기본 설정은 다음과 같습니다.

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

그리고 C ++의 경우

-ansi -pedantic -Wall -Wextra -Weffc++

( -WerrorC ++를 건너 뛰면 -Weffc++약간의 성가심이 있습니다)


10
-Werror 예를 들어, 경고의 특정 유형에 대해 사용할 수 있습니다 -Werror -Weffc ++ -Wno 오류 = effc ++
로버트 Hensing

2
ansi : C 모드에서는 -std=c89. C ++ 모드에서는 -std=c++98. 즉, 개봉 된 다른 지정하는 경우 std, 그나마 사용ansi
숀 브레 켄 리지

2

시험

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

그것은 확실히 약간의 조정이 필요한 빠르고 더러운 시작입니다. 한 가지 이유는 컴파일러를 해당 언어 (예 : g++C ++) 로 호출하더라도 해당 언어에 적용되지 않는 경고를 받게됩니다 (그리고 컴파일러는 손을 내밀고 경고 제거).

또 다른 한 가지는에서 추가 한 것입니다 -Werror. 경고를 수정하지 않는 경우 경고를 켜는 데 관심이있는 이유는 무엇입니까? 목록에서 경고를 제거 할 수도 있습니다. (예를 들어 -Waggregate-returnC ++ 에서는 거의 사용하지 않습니다 .)

일부 경고는 다른 성능 관련 옵션 ( -Wstack-protector) 없이는 아무 작업도 수행하지 않습니다 . -fdiagnostics-show-optionGCC 매뉴얼은 당신의 친구입니다.

그런데 일부 경고는 상호 배타적입니다. 사용 특히 -Wtraditional-Wold-style-definition함께 -Werror, 컴파일되지 않습니다.


0

내 Clion의 CmakeLists.txt에서

cmake_minimum_required(VERSION 3.13)
project(cpp17)

set(CMAKE_CXX_STANDARD 17)

set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
 -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline -Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )

add_executable(cpp17 main.cpp)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.