IT story

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

hot-time 2020. 8. 2. 17:21
반응형

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


종종 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++있습니까? (나는 그들 중 다수가 동일하다는 것을 알고 있습니다.)


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

-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에서는 평소와 같이 릴리스 빌드에서는 작동하지 않습니다. 즉, 네트워크 연결이나 절대 제어 할 수없는 데이터베이스에서 얻은 숫자의 유효성을 검증하기 위해이 값에 의존 할 수 없습니다. 예외 또는 조기 반납이이를 처리하는 가장 좋은 방법입니다 (그러나 여전히 기본 사례가 필요합니다!).

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

그런 다음 위 목록에 포함되지 않은 일련의 경고가 있습니다. 다음은 경고와 기본 목록에 포함되지 않은 이유에 대한 의견입니다.

없는 경고 :

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

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

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

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

  • -Winline is absent because I don't use the inline keyword for optimization purposes, just to define functions inline in headers. I don't care if the optimizer actually inlines it. This warning also complains if it can't inline a function declared in a class body (such as an empty virtual destructor).

  • -Winvalid-pch is missing because I don't use precompiled headers.

  • -Wmissing-format-attribute is not used because I do not use gnu extensions. Same for -Wsuggest-attribute and several others

  • Potentially notable for its absence is -Wno-long-long, which I have no need for. I compile with -std=c++0x (-std=c++11 in GCC 4.7), which includes long long integer types. Those stuck back on C++98 / C++03 may consider adding that exclusion from the warning list.

  • -Wnormalized=nfc is already the default option, and looks to be the best.

  • -Wpadded is turned on occasionally to optimize the layout of classes, but it is not left on because not all classes have enough elements to remove padding at the end. In theory I could get some extra variables for 'free', but it's not worth the extra effort of maintaining that (if my class size changes, it's not easy to remove those previously free variables).

  • -Wstack-protector is not used because I do not use -fstack-protector

  • -Wstrict-aliasing=3 is turned on by -Wall and is the most accurate, but it looks like level 1 and 2 give more warnings. In theory a lower level is a 'stronger' warning, but it's at the cost of more false positives. My own test code compiled cleanly under all 3 levels.

  • -Wswitch-enum isn't behavior that I want. I don't want to handle every switch statement explicitly. It would be useful if the language had some mechanism to activate this on specified switch statements (to ensure that future changes to the enum are handled everywhere that they need to be), but it's overkill for an "all-or-nothing" setting.

  • -Wunsafe-loop-optimizations causes too many spurious warnings. It may be useful to apply this one periodically and manually verify the results. As an example, it generated this warning in my code when I looped over all elements in a vector to apply a set of functions to them (using the range-based for loop). It is also warning for the constructor of a const array of const std::string (where this is no loop in user code).

  • -Wzero-as-null-pointer-constant and -Wuseless-cast are GCC-4.7-only warnings, which I will add when I transition to GCC 4.7.

I've filed a few bug reports / enhancement requests at gcc as a result of some of this research, so hopefully I'll be able to eventually add more of the warnings from the "do not include" list to the "include" list. This list includes all warnings mentioned in this thread (plus I think a few extra). Many of the warnings not explicitly mentioned in this post are included as part of another warning I do mention. If anyone notices any warnings that are excluded from this post entirely, let me know.

edit: It looks like I had missed several (which I have now added in). There is actually a second page at http://gcc.gnu.org that is quite well hidden. General warning options and C++ options (scroll down to the bottom for warnings)


D'oh, all of my original searches turned up 99% of posts on how to suppress warnings (scarily enough), but I just ran across this comment, which has this lovely set of flags (some less relevant):

Cross checked with:

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

So, I think that's a good starting point. Didn't realize this was a dupe, but at least it was deeply buried. :-)


Some of those are already included in -Wall or -Wextra.

A good base setup for C is:

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

and for C++

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

(skipping -Werror for C++ since -Weffc++ has some annoyances)


Try

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

That's a quick and dirty start which will definitely need some tuning; for one thing, even if you call the compiler by the appropriate name for your language (e.g. g++ for C++), you will get warnings that don't apply to that language (and the compiler will throw up its hands and refuse to continue until you remove the warning).

Another thing is that I added in -Werror, because if you aren't fixing the warnings, why do you care about turning them on? You can also take warnings out of the list. (For example, I almost never use -Waggregate-return with C++.)

Some warnings won't do anything without other performance related options (-Wstack-protector). -fdiagnostics-show-option and the GCC manual are your friends.

By the way, some warnings are mutually exclusive; in particular using -Wtraditional and -Wold-style-definition along with -Werror, will not compile.


In my Clion's 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)

참고URL : https://stackoverflow.com/questions/5088460/flags-to-enable-thorough-and-verbose-g-warnings

반응형