C에 유용한 GCC 플래그


157

setting -Wall과 setting 외에도 -std=XXXC에서 사용하기에 실제로 유용하지만 덜 알려진 컴파일러 플래그는 무엇입니까?

특히 추가 경고에 관심이 있으며 우발적 인 유형 불일치를 최소화하기 위해 경고를 오류로 전환하는 경우가 있습니다.


9
-save-temps, -Wshadow그리고 -fmudflap내가 아는하지 않은 가장 큰 발견은, 모두에게 감사했다.
Matt Joiner

내가 알 수있는 한 컨텍스트 : gcc -c [flags-go-here] -o myprog.o myprog.cC 프로그램을 컴파일 (링크가 아님)하기 위해 실행 중 입니다.
Rory O'Kane

답변:


64

몇 가지 -f코드 생성 옵션이 흥미 롭습니다.

  • -ftrapv함수는 프로그램이 부호있는 정수 오버 플로우 (공식적으로 C에서 "정의되지 않은 동작")에서 중단되도록합니다.

  • -fverbose-asm-S어셈블리 출력을 검사하기 위해 컴파일 할 때 유용합니다 . 유익한 주석이 추가됩니다.

  • -finstrument-functions 모든 기능 시작 및 종료 지점에서 사용자 제공 프로파일 링 함수를 호출하는 코드를 추가합니다.


에 대해 -ftrapv여기를 살펴보십시오. stackoverflow.com/questions/20851061/… .. 긴 버그가 수정되기를 기다리는 것 같습니다.
Arjun Sreedharan

위의 의견을 확인할 수 있습니까?
Suraj Jain

-ftrapv는 본질적으로 -fsanitize = signed-integer-overflow로 대체되었습니다.
Marc Glisse

139

여기 내 것이 있습니다 :

  • -Wextra, -Wall: 필수.
  • -Wfloat-equal: 일반적으로 부동 소수점 숫자가 동일한 지 테스트하는 것이 좋지 않기 때문에 유용합니다.
  • -Wundef: #if지시문 에서 초기화되지 않은 식별자가 평가되면 경고합니다 .
  • -Wshadow: 지역 변수가 다른 지역 변수, 매개 변수 또는 전역 변수를 가리거나 내장 함수가 그림자 될 때마다 경고합니다.
  • -Wpointer-arith: 함수 크기 또는 크기에 따라 달라지는 경우 경고합니다 void.
  • -Wcast-align: 대상의 필요한 정렬이 증가하도록 포인터를 캐스트 할 때마다 경고합니다. 예를 들어 정수가 2 바이트 또는 4 바이트 경계에서만 액세스 할 수있는 컴퓨터에서 a char *가 캐스팅 된 경우 경고합니다 int *.
  • -Wstrict-prototypes: 인수 유형을 지정하지 않고 함수가 선언되거나 정의되면 경고합니다.
  • -Wstrict-overflow=5: 부호있는 오버플로가 발생하지 않는다는 가정에 따라 컴파일러가 최적화되는 경우에 대해 경고합니다. (값 5가 너무 엄격 할 수 있습니다. 매뉴얼 페이지를 참조하십시오.)
  • -Wwrite-strings: 문자열 상수에 const char[길이를] 지정하여 주소의 주소를 비 const char *포인터에 복사하면 경고가 표시됩니다.
  • -Waggregate-return: 구조체 나 공용체를 반환하는 함수가 정의되거나 호출되면 경고합니다.
  • -Wcast-qual: 대상 유형 * 에서 유형 한정자를 제거하기 위해 포인터를 캐스트 할 때마다 경고 합니다.
  • -Wswitch-default: switch문장에 default대소 문자 가 없을 때마다 경고합니다 * .
  • -Wswitch-enum: switch명령문에 열거 된 유형의 색인이 있고 case해당 열거의 명명 된 코드 중 하나 이상에 대해 a가 없을 때 경고합니다 * .
  • -Wconversion: 값을 변경할 수있는 암시 적 변환에 대해 경고합니다 * .
  • -Wunreachable-code: 컴파일러에서 해당 코드가 실행되지 않음을 감지하면 경고합니다 * .

* 표시가있는 사람들은 때때로 너무 많은 가짜 경고를하므로 필요에 따라 사용합니다.


11
꽤 완전한 목록입니다. 하나만 추가하고 싶습니다. -Wformat=2: printf / scanf 기능에 대한 추가 형식 확인.
schot

1
이 모든 것을 암시하지 -Wall않습니까?
chacham15

2
@ chacham15, 아니요, 그렇게 생각하지 않습니다. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Alok Singhal

1
@ Alok 흠, 아마도 배포판에서 표준이 아닐까요? 내 mbp에서 나는 -Wwrite-strings그것을 너무 싫어하기 때문에 명시 적으로 꺼야한다는 것을 알고 있습니다.
chacham15

아마 @ chacham15. 그러나 대한 설명은 -Wwrite-strings구체적으로는의 일부가 아닌 말한다 -Wall: gcc.gnu.org/onlinedocs/gcc/... . 어쩌면 설정에서 다른 것이 그 플래그를 설정하고 있습니까? 아니면 C ++를 컴파일하고 있습니까?
Alok Singhal

52

항상 사용 -O이상 ( -O1, -O2, -Os, 등). 기본 최적화 수준에서 gcc는 컴파일 속도를 결정하고 단위 변수와 같은 것에 대해 경고하기에 충분한 분석을 수행하지 않습니다.

-Werror컴파일을 중지하지 않는 경고는 무시되는 경향이 있으므로 정책을 고려하십시오 .

-Wall 오류 일 가능성이 높은 경고를 거의 설정합니다.

포함 된 경고는 -Wextra일반적인 합법적 인 코드를 표시하는 경향이 있습니다. 코드 검토에 유용 할 수 있지만 (보풀이 많은 프로그램은 더 많은 함정이 더 유연하다는 것을 알지만) 정상적인 개발을 위해 설정하지는 않습니다.

-Wfloat-equal 프로젝트의 개발자가 부동 소수점에 익숙하지 않은 경우 좋은 아이디어이고 그렇지 않은 경우 나쁜 아이디어입니다.

-Winit-self유용하다; 에 포함되지 않은 이유가 궁금합니다 -Wuninitialized.

-Wpointer-arith와 호환되지 않는 대부분 이식 가능한 코드가있는 경우 유용합니다 -pedantic.


9
"-Wfloat-equal +1은 프로젝트의 개발자가 부동 소수점에 익숙하지 않은 경우 좋은 아이디어이고, 그렇지 않은 경우 나쁜 아이디어입니다." 특히 후반부. :-)
R .. GitHub 중지 지원 얼음

39
-save-temps

이것은 전 처리기 및 어셈블리의 결과를 남깁니다.

사전 처리 된 소스는 매크로 디버깅에 유용합니다.

이 어셈블리는 어떤 최적화가 적용되었는지 확인하는 데 유용합니다. 예를 들어 GCC가 일부 재귀 함수에서 테일 콜 최적화를 수행하고 있는지 확인할 수 있습니다. 그렇지 않으면 스택 오버플로가 발생할 수 있습니다.


나는 당신이 그것을 어떻게하는지 궁금해했습니다 ... 나는 단지 gcc에게 어셈블리가 필요할 경우 어셈블리를 덤프하도록 요청했습니다.

35

아무도 이것에 대해 아직 말하지 않은 것에 놀랐습니다. 내가 염려하는 한 가장 유용한 플래그는 -g디버깅 정보를 실행 파일에 넣어 디버깅하고 소스를 단계별로 실행할 수있는 것입니다. 등 stepi프로그램의 명령)이 실행하는 것 동안.


35

-fmudflap -UB를 잡기 위해 모든 위험한 포인터 작업에 런타임 검사를 추가합니다. 이를 통해 프로그램이 버퍼 오버플로를 다시 효과적으로 예방하고 모든 종류의 매달려있는 포인터를 잡을 수 있습니다.

데모는 다음과 같습니다.

$ cat mf.c 
int main()
{
 int a[10];
 a[10]=1; // <-- o noes, line 4
}

$ gcc -fmudflap mf.c -lmudflap
$ ./a.out 
*******
mudflap violation 1 (check/write): time=1280862302.170759 ptr=0x7fff96eb3d00 size=44
pc=0x7f3a575503c1 location=`mf.c:4:2 (main)'
      /usr/lib/libmudflap.so.0(__mf_check+0x41) [0x7f3a575503c1]
      ./a.out(main+0x90) [0x400a54]
      /lib/libc.so.6(__libc_start_main+0xfd) [0x7f3a571e2c4d]
Nearby object 1: checked region begins 0B into and ends 4B after
mudflap object 0xf9c560: name=`mf.c:3:6 (main) a'
bounds=[0x7fff96eb3d00,0x7fff96eb3d27] size=40 area=stack check=0r/3w liveness=3
alloc time=1280862302.170749 pc=0x7f3a57550cb1
number of nearby objects: 1

흠, mudflap은 꽤 불쾌한 것 같습니다 : P
Matt Joiner

9
-fmudflapGCC 4.9 이후 더 이상 지원되지 않습니다 warning: switch '-fmudflap' is no longer supported. AddressSanitizer로 대체되었습니다.
Agostino

21

실제로 C / C ++와 관련이 없지만 어쨌든 유용합니다.

@file

위의 모든 좋은 플래그 (모두 지정한)를 'file'에 넣고 위의 플래그를 사용하여 해당 파일의 모든 플래그를 함께 사용하십시오.

예 :

파일 : compilerFlags

-벽

-std = c99

-엑스트라

그런 다음 컴파일하십시오.

gcc yourSourceFile @compilerFlags

15

-march=native 컴파일하는 플랫폼 (= 칩)에 최적화 된 코드 생성


2
대상을 모르는 비원시 시스템을 위해 컴파일하는 경우 명령 세트를 사용하지 않고 최적화하는 mtune = xxx를 사용할 수 있습니다. 예를 들어 mtune = generic은 "평균"케이스 프로세서로 최신 상태로 유지됩니다.
Turix

15

컴파일러에서 사전 정의한 전 처리기 플래그를 알아야하는 경우 :

echo | gcc -E -dM -

13

실제로 오류를 감지하는 데 도움이되지는 않지만 거의 언급되지 않은 -masm=intel옵션은 -S어셈블리 출력을 훨씬 더 잘 검사하는 데 사용 됩니다.

AT & T 어셈블리 구문으로 인해 머리가 너무 아파요.


2
AT & T와 Intel의 차이점은 C #과 Java의 차이점입니다. 그냥 구문. 둘 다 끔찍 해요 :)
Matt Joiner

2
+1 @michael은 gcc가 신 대신 끔찍한 대신 인텔 구문을 사용하도록합니다. 검사 어셈블리는 충분한 두뇌주기를 사용하므로 src가 opcode에서 이전에 수행 한 두뇌주기를 낭비 할 필요가 없습니다. 이제 gcc만이 다른 컴파일러와 같이 __asm ​​{} 인라인을 지원한다면 모두 설정되었습니다!
greatwolf

10

내 makefile에는 일반적으로

  CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
  ...
  g++ $(CFLAGS) -o junk $<
  gcc $(CFLAGS) -o $@ $<
  rm -f junk

이러한 옵션 중 가장 중요한 것은 이전에 논의되었으므로 아직 지적되지 않은 두 가지 기능을 지적하겠습니다.

내가 그 코드베이스에서 일하고 있어요 비록 요구 사항이 일부 플랫폼 이식성에 대한 일반 C로 여전히 더 괜찮은 C ++ 컴파일러가없는, 내가 (C 컴파일러뿐만 아니라) C ++ 컴파일러와의 "추가"컴파일을한다. 3 가지 이점이 있습니다.

  1. C ++ 컴파일러는 때때로 C 컴파일러보다 더 나은 경고 메시지를 제공합니다.
  2. C ++ 컴파일러는 -Weffc ++ 옵션을 허용합니다.이 옵션은 때로는 유용한 팁을 제공합니다. 평범한 C로만 컴파일하면 놓칠 수 있습니다.
  3. 일반 C 코드가 유효하지 않은 C ++ 코드 (예 : "bool"이라는 변수 정의)가 아닌 몇 가지 경계 조건을 피하면서 코드를 C ++로 이식하기가 비교적 쉽습니다.

네, 생각을 계속 절망적으로 낙관적 인 낙천적이야 그 확실히 어떤 달 이제 하나 개의 플랫폼이 하나 ++ 폐기 선언, 또는 괜찮은 C ++ 컴파일러를 얻을, 우리는 결국 C로 전환 할 수 있습니다됩니다. 내 마음에, 그것은 불가피하다-유일한 질문은 경영진이 모든 사람을 조랑말로 발행하기 전 또는 후에 발생하는지 여부이다. :-)


C ++로 작성하면 좋은 점이 있습니다. (자연스럽게 서브셋)
Matt Joiner

6
C ++에 찬성하여 C가 더 이상 사용되지 않는 것은 결코 일어나지 않을 것임을 지적해야합니다. 죄송합니다 :)
Matt Joiner

4
고려 -o을 / dev / null 대신 RM -f 정크
ulidtko

9
-Wstrict-prototypes -Wmissing-prototypes

10
그리고 -Wold-style-definition프로토 타입 선언에서도 K & R 스타일 함수가 좋은 생각이라고 생각하는 상호 주의자를 다루어야합니다. (저는 그런 사람들을 다뤄야합니다. K & R로 작성된 새 코드를 찾으면 정말 짜증납니다. 수정되지 않은 레거시 K & R 자료를 가지고있는 것이 좋지만 새로운 코드입니다! Grump !!!)
Jonathan Leffler

9

언급되지 않은 훌륭한 깃발은 다음과 같습니다.

-Werror-implicit-function-declaration

선언되기 전에 함수가 사용될 때마다 오류를 제공하십시오.


8
man gcc

매뉴얼에는 좋은 설명이 담긴 흥미로운 깃발이 가득합니다. 그러나 -Wall은 아마도 gcc를 가능한 한 장황하게 만들 것입니다. 더 흥미로운 데이터를 원한다면 valgrind 또는 오류를 확인하기위한 다른 도구를 살펴보십시오.


1
그래도 loooooooooooooooooooooooooooooooong입니다. man gcc | nl11000 라인 이상을보고합니다. 그것은 악명 높은 bash맨 페이지 이상입니다 !
새로운 123456

12
그들이 탐색 할 수없는 "정보"페이지 중 하나 대신 맨 페이지에 넣은 것을 감사합니다.
Matt Joiner

6

글쎄, -Wextra표준이어야한다. -Werror경고를 오류로 바꿉니다 ( 특히없이 컴파일하면 매우 성 가실 수 있습니다 -Wno-unused-result). C99 기능을 사용하는 경우 -pedantic와 함께 std=c89추가 경고가 표시됩니다.

그러나 그것은 그것에 관한 것입니다. C 컴파일러를 C 자체보다 유형이 더 저렴한 것으로 조정할 수 없습니다.


6

-M* 옵션 군.

이를 통해 c 또는 c ++ 소스 파일이 의존해야하는 헤더 파일을 자동으로 알아내는 make 파일을 작성할 수 있습니다. GCC는이 의존성 정보로 make 파일을 생성 한 다음 기본 make 파일에서이를 포함시킵니다.

다음은 c ++ 소스 및 헤더 파일로 가득 찬 디렉토리를 컴파일하고 모든 종속성을 자동으로 알아내는 -MD 및 -MP를 사용하는 매우 일반적인 makefile의 예입니다.

CPPFLAGS += -MD -MP                                         
SRC = $(wildcard *.cpp)                                                       

my_executable: $(SRC:%.cpp=%.o)                                                        
        g++ $(LDFLAGS) -o $@ $^                                               

-include $(SRC:%.cpp=%.d)

보다 자세한 내용을 다루는 블로그 게시물은 다음과 같습니다. http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html


6

-Werror모든 경고를 오류로 취급하고 컴파일을 중지하는가 있습니다 . gcc매뉴얼 페이지는 컴파일러에 대한 모든 명령 줄 스위치에 대해 설명합니다.


@Matt Joiner : 어떤 머신 아키텍처를 사용하고 있는지 언급하지 않았으므로 gcc플래그는 사용자와 다른 사람이 제안 할 수있는 링크마다 다를 수 있습니다. 매뉴얼 페이지가 소프트웨어와 함께 제공되는 이유입니다.
Greg Hewgill

4

-Wfloat-equal

보낸 사람 : http://mces.blogspot.com/2005/07/char-const-argv.html

내가 좋아하는 다른 새로운 경고 중 하나는 -Wfloat-equal입니다. 평등 조건에서 부동 소수점 숫자를 가질 때마다 경고합니다. 그것은 화려합니다! 모든 컴퓨터 그래픽 또는 (질서 :) 계산 기하학 알고리즘이 프로그래밍 된 경우 두 개의 부동 소수점이 동등성과 일치하지 않는다는 것을 알고 있습니다.


10
내가하고있는 일을 알면서 내 수레 평등과 일치합니다.
Roland Illig

4

이 스레드가 특정 문제를 해결하기 위해 플래그를 찾고 있다는 것을 알았습니다. 여기에 표시되지 않으므로 게시물에 저를 비웃는 것을 추가 할 것입니다 .

-Wformat=2플래그

-Wformat=> printf및에 대한 호출을 scanf확인하여 제공된 인수에 지정된 형식 문자열에 적합한 유형이 있는지 확인하십시오.

그리고 GCC 매뉴얼에 따르면 실제로 중요한 부분은 다음과 같습니다.

-Wformat에 포함되어 -Wall있습니다. , 옵션을 체크 형식의 일부 측면을 더 제어를 위해 -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, 및 -Wformat=2사용할 수 있지만 -Wall.`에 포함되지 않습니다

그래서, 당신은 단지 때문에 -Wall의미하지 않는다 당신은 모든 것을 가지고있다. ;)


3

때로는 -s훨씬 작은 실행 파일에 사용합니다.

-s
    Remove all symbol table and relocation information from the executable.

출처 : http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options


6
strip바이너리에서 실행해야 합니다. 이런 식으로 디버그 정보가있는 바이너리를 가질 수 있습니다. 나중에 배포하기 위해 제거하십시오.
Hasturkun

그렇습니다. strip작동하지만 -s더 빠르고 쉬울 수는 있지만 달리는 것만 큼 정교하지는 않습니다.strip
Vasiliy Sharapov

3

이 답변은 약간 주제가 맞지 않을 수 있지만 질문은 나에게서 가치있는 +1이지만

특히 추가 경고에 관심이 있으며 우발적 인 유형 불일치를 최소화하기 위해 경고를 오류로 전환하는 경우가 있습니다.
간파해야하는 도구가 모두 명확하지 않을 수있는 오류와 오류 가능성이있다, 부목 이럴 gcc가 또는 그 문제에 대한 모든 다른 컴파일러에 비해 오류를 잡기에 더 나은 방법 일을한다. 그것은 당신의 도구 가슴에 가치있는 도구입니다.

스플린트와 같은 린트 유형의 도구를 통한 정적 검사는 컴파일러 도구 체인의 일부 여야합니다.


항상 오류가 C : \ include에있는 프리 프로세서 파일을 제출할 수 없음을 표시합니다. 어떻게해야할지 모르겠습니다
Suraj Jain

2

추가 경고에 특히 관심이 있습니다.

또한 -Wall, -W또는 -Wextra옵션 ( -W이전 버전의 gcc 및 최신 버전에서 작동합니다. 최신 버전은 대체 이름을 지원합니다 -Wextra. 이는 같은 것을 의미하지만 더 설명적임)은 다양한 추가 경고를 가능하게합니다.

일반적으로 더 의심스러운 것들에 대해 더 많은 경고가 가능하지 않습니다. 사용 가능한 옵션 세트는 사용중인 gcc 버전에 따라 다릅니다. 자세한 내용은 문의 man gcc하거나 관심있는 특정 gcc 버전에 대한 온라인 설명서info gcc참조하십시오 . 사용중인 특정 표준에 필요한 모든 경고를 표시합니다 ( 또는 )와 같은 다른 옵션 에서 gcc 확장 프로그램 사용에 대해 불평합니다.-pedantic-std=xxx-ansi

우발적 인 유형 불일치를 최소화하기 위해 경고를 오류로 전환하는 경우도 있습니다.

-Werror모든 경고를 오류로 바꿉니다. 그래도 gcc를 사용하면 특정 경고에 대해 선택적으로 그렇게 할 수 있다고 생각하지 않습니다.

-Werror외부 라이브러리의 헤더 파일이 일부를 트립 할 수 있으므로 프로젝트별로 (특히 사용하는 경우 ) 경고를 선택적으로 선택해야 할 수도 있습니다. ( -pedantic특히 내 경험상 이런 점에서 도움이되지 않는 경향이 있습니다.)


4
"gcc가 특정 경고에 대해 선택적으로 그렇게 할 수 있다고 생각하지 않습니다." 실제로, 당신은 할 수 있습니다 -Werror=some-warning.
Matthew Flaschen

0
  • -Wmissing-prototypes: 글로벌 함수가 이전 프로토 타입 선언없이 정의 된 경우.
  • -Wformat-security: 가능한 보안 문제를 나타내는 형식 함수 사용에 대해 경고합니다. 현재,이 호출에 대해 경고 printfscanf형식 문자열은 문자열 리터럴없는 기능과 어떠한 형식 인수가 없습니다

0
  • -Werror=return-type: gcc에서 함수가 반환되지 않으면 오류를 적용합니다. 그것은이다 /we4716Visual Studio에서.

  • -Werror=implicit-function-declaration: 정의 / 포함되지 않은 기능을 사용할 때 오류를 시행합니다. 그것은이다 /we4013Visual Studio에서.

  • -Werror=incompatible-pointer-types: 포인터 유형이 예상 포인터 유형과 일치하지 않을 때 오류가 발생합니다. 그것은이다 /we4133Visual Studio에서.

실제로 C 코드를 크로스 플랫폼으로 유지하고 CMake를 사용하고 제공된 cflags를 다음과 같이 CMakeLists.txt에 넣습니다.

if (CMAKE_SYSTEM_NAME MATCHES "Windows")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we4013 /we4133 /we4716")
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -Werror=return-type")
endif()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.