Oprócz ustawiania -Wall
i ustawiania -std=XXX
, jakie inne naprawdę przydatne, ale mniej znane flagi kompilatora są dostępne do użytku w C?
Szczególnie interesują mnie wszelkie dodatkowe ostrzeżenia i / lub przekształcanie ostrzeżeń w błędy w niektórych przypadkach, aby całkowicie zminimalizować wszelkie przypadkowe niezgodności typów.
c
gcc
compiler-flags
Matt Joiner
źródło
źródło
-save-temps
,-Wshadow
i-fmudflap
były to największe znaleziska, o których nie wiedziałem, dzięki wszystkim.gcc -c [flags-go-here] -o myprog.o myprog.c
aby skompilować (nie połączyć) program w C.Odpowiedzi:
Kilka
-f
opcji generowania kodu jest interesujących:-ftrapv
Funkcja powoduje przerwanie programu w liczba całkowita ze znakiem przelewowy (formalnie „zdefiniowana zachowanie” w C).-fverbose-asm
jest przydatny, jeśli kompilujesz z,-S
aby zbadać wyjście zestawu - dodaje kilka pouczających komentarzy.-finstrument-functions
dodaje kod wywołujący funkcje profilowania dostarczone przez użytkownika w każdym punkcie wejścia i wyjścia funkcji.źródło
-ftrapv
zajrzyj tutaj stackoverflow.com/questions/20851061/… .. wygląda na to, że błąd długo czekał na naprawę.Oto moje:
-Wextra
,-Wall
: niezbędny.-Wfloat-equal
: przydatne, ponieważ zwykle testowanie liczb zmiennoprzecinkowych pod kątem równości jest złe.-Wundef
: ostrzeż, jeśli niezainicjowany identyfikator jest oceniany w#if
dyrektywie.-Wshadow
: ostrzegaj za każdym razem, gdy zmienna lokalna przesłania inną zmienną lokalną, parametr lub zmienną globalną lub gdy funkcja wbudowana jest zasłonięta.-Wpointer-arith
: ostrzeż, jeśli cokolwiek zależy od rozmiaru funkcji lubvoid
.-Wcast-align
: ostrzegaj za każdym razem, gdy wskaźnik jest rzucany w taki sposób, że wymagane wyrównanie celu jest zwiększone. Na przykład ostrzegaj, jeśli achar *
jest rzutowaneint *
na maszynę, na której liczby całkowite są dostępne tylko w granicach dwu- lub czterobajtowych.-Wstrict-prototypes
: warn, jeśli funkcja jest zadeklarowana lub zdefiniowana bez określenia typów argumentów.-Wstrict-overflow=5
: ostrzega o przypadkach, w których kompilator optymalizuje na podstawie założenia, że podpisane przepełnienie nie występuje. (Wartość 5 może być zbyt rygorystyczna, zobacz stronę podręcznika).-Wwrite-strings
: nadaje stałym łańcuchowymconst char[
długość typu]
, aby kopiowanie adresu jednego do innegoconst char *
wskaźnikiem otrzymało ostrzeżenie.-Waggregate-return
: ostrzega, jeśli jakiekolwiek funkcje zwracające struktury lub związki są zdefiniowane lub wywołane.-Wcast-qual
: ostrzegaj za każdym razem, gdy rzutowany jest wskaźnik w celu usunięcia kwalifikatora typu z typu docelowego * .-Wswitch-default
: ostrzegaj za każdym razem, gdyswitch
instrukcja nie madefault
przypadku * .-Wswitch-enum
: ostrzegaj za każdym razem, gdyswitch
instrukcja ma indeks typu wyliczeniowego i brakuje jejcase
dla jednego lub więcej nazwanych kodów tego wyliczenia * .-Wconversion
: ostrzegaj przed niejawnymi konwersjami, które mogą zmienić wartość * .-Wunreachable-code
: warn, jeśli kompilator wykryje, że kod nigdy nie zostanie wykonany * .Te oznaczone * czasami dają zbyt wiele fałszywych ostrzeżeń, więc używam ich w razie potrzeby.
źródło
-Wformat=2
: Dodatkowy format sprawdza funkcje printf / scanf.-Wall
?-Wwrite-strings
ponieważ tak bardzo go nienawidzę.-Wwrite-strings
konkretnie mówi, że nie jest on częścią-Wall
: gcc.gnu.org/onlinedocs/gcc/… . Może coś innego w twojej konfiguracji ustawia tę flagę? A może kompilujesz C ++?Zawsze stosować
-O
lub powyżej (-O1
,-O2
,-Os
, itd.). Na domyślnym poziomie optymalizacji gcc dąży do szybkości kompilacji i nie przeprowadza wystarczającej analizy, aby ostrzegać o takich rzeczach, jak zmienne zjednostkowane.Rozważ ustalenie
-Werror
zasad, ponieważ ostrzeżenia, które nie zatrzymują kompilacji, są zwykle ignorowane.-Wall
prawie włącza ostrzeżenia, które najprawdopodobniej są błędami.Ostrzeżenia zawarte w programie
-Wextra
zwykle oznaczają typowy, legalny kod. Mogą być przydatne do recenzji kodu (chociaż programy typu lint mają dużo więcej pułapek jest bardziej elastycznych), ale nie włączałbym ich do normalnego programowania.-Wfloat-equal
to dobry pomysł, jeśli programiści projektu nie znają zmiennoprzecinkowych, a zły pomysł, jeśli tak jest.-Winit-self
jest przydatny; Zastanawiam się, dlaczego nie ma tego w-Wuninitialized
.-Wpointer-arith
jest przydatny, jeśli masz kod w większości przenośny, z którym nie działa-pedantic
.źródło
Pozostawia to wyniki preprocesora i asemblacji.
Wstępnie przetworzone źródło jest przydatne do debugowania makr.
Zespół jest przydatny do określenia, jakie optymalizacje zostały wprowadzone. Na przykład możesz chcieć sprawdzić, czy GCC optymalizuje wywołania końcowe w niektórych funkcjach rekurencyjnych, ponieważ bez niej możesz potencjalnie przepełnić stos.
źródło
Dziwię się, że nikt jeszcze tego nie powiedział - najbardziej użyteczną flagą, o ile mi
-g
wiadomo , jest umieszczanie informacji debugowania w pliku wykonywalnym, tak aby można było je zdebugować i przejść przez źródła (chyba że jesteś biegły i czytasz asembler i jakstepi
polecenie) programu podczas jego wykonywania.źródło
-fmudflap - dodaje testy uruchomieniowe do wszystkich ryzykownych operacji wskaźnikowych, aby złapać UB. To skutecznie uodparnia Twój program na przepełnienie bufora i pomaga wyłapać wszelkiego rodzaju wiszące wskazówki.
Oto demo:
źródło
-fmudflap
nie jest już obsługiwany od GCC 4.9warning: switch '-fmudflap' is no longer supported
. Został zastąpiony przez AddressSanitizer.Niezupełnie związane z C / C ++, ale i tak przydatne:
Umieść wszystkie powyższe dobre flagi (które wszyscy określiliście) w „pliku” i użyj powyższej flagi, aby użyć razem wszystkich flag w tym pliku.
na przykład:
Plik: compilerFlags
Następnie skompiluj:
źródło
-march=native
aby stworzyć zoptymalizowany kod dla platformy (= chipa), na którym kompilujeszźródło
Jeśli potrzebujesz znać flagi preprocesora, które są predefiniowane przez kompilator:
źródło
Nie jest to zbyt pomocne w wykrywaniu błędów, ale rzadko wspominana
-masm=intel
opcja sprawia, że używa-S
do sprawdzania wyników zespołu jest o wiele przyjemniejsze.Składnia asemblera AT&T za bardzo boli mnie w głowę.
źródło
Mój plik makefile zazwyczaj zawiera
Najważniejsze z tych opcji zostały omówione wcześniej, dlatego zwrócę uwagę na dwie funkcje, które nie zostały jeszcze wymienione:
Mimo że pracuję nad bazą kodu, która musi być zwykłym C, aby można było ją przenieść na jakąś platformę, która nadal nie ma porządnego kompilatora C ++, wykonuję „dodatkową” kompilację za pomocą kompilatora C ++ (oprócz kompilatora C). Ma to 3 zalety:
Tak, jestem beznadziejnie optymistyczną Pollyanną, która wciąż myśli, że z pewnością w każdym miesiącu jedna platforma zostanie uznana za przestarzałą lub zdobędzie porządny kompilator C ++ i możemy wreszcie przejść na C ++. Moim zdaniem jest to nieuniknione - pozostaje tylko pytanie, czy dzieje się to przed, czy po tym, jak zarząd ostatecznie wyda każdemu kucyka. :-)
źródło
źródło
-Wold-style-definition
jeśli masz do czynienia z recydywistami, którzy uważają, że funkcje w stylu K&R są dobrym pomysłem, nawet z prototypowymi deklaracjami. (Muszę mieć do czynienia z takimi ludźmi. Naprawdę denerwuje mnie, gdy znajduję nowy kod napisany w K&R. Wystarczająco źle jest mieć starsze elementy K&R, które nie są naprawione, ale nowy kod! Grump !!!)Oto wspaniała flaga, o której nie wspomniano:
Podaj błąd za każdym razem, gdy funkcja jest używana przed zadeklarowaniem.
źródło
Podręcznik jest pełen ciekawych flag z dobrymi opisami. Jednak -Wall prawdopodobnie sprawi, że gcc będzie tak rozwlekłe, jak to tylko możliwe. Jeśli potrzebujesz bardziej interesujących danych, powinieneś rzucić okiem na valgrind lub inne narzędzie do sprawdzania błędów.
źródło
man gcc | nl
zgłasza ponad 11000 linii. To więcej niż niesławna stronabash
podręcznika!Cóż, też
-Wextra
powinno być standardowe.-Werror
zamienia ostrzeżenia w błędy (co może być bardzo irytujące, zwłaszcza jeśli kompilujesz bez niej-Wno-unused-result
).-pedantic
w połączeniu zstd=c89
daje dodatkowe ostrzeżenia, jeśli używasz funkcji C99.Ale to jest o tym. Nie można dostroić kompilatora C do czegoś bardziej zachowującego typy niż sam C.
źródło
-M*
rodzina opcji.Umożliwiają one pisanie plików, które automatycznie określają, od jakich plików nagłówkowych powinny zależeć pliki źródłowe c lub c ++. GCC wygeneruje pliki make z tymi informacjami o zależnościach, a następnie dodasz je do swojego podstawowego pliku make.
Oto przykład niezwykle ogólnego pliku makefile używającego -MD i -MP, który skompiluje katalog pełen plików źródłowych i nagłówkowych języka c ++ i automatycznie obliczy wszystkie zależności:
Oto post na blogu, który omawia to bardziej szczegółowo: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html
źródło
Jest
-Werror
, który traktuje wszystkie ostrzeżenia jako błędy i zatrzymuje kompilację. Stronagcc
podręcznika wyjaśnia wszystkie przełączniki wiersza poleceń dla twojego kompilatora.źródło
gcc
flagi mogą się różnić między twoją i jakimkolwiek linkiem, który ktoś zasugeruje. Dlatego z oprogramowaniem dostarczane są strony podręcznika.-Wfloat-equal
Od: http://mces.blogspot.com/2005/07/char-const-argv.html
źródło
Znalazłem ten wątek, szukając flagi do naprawienia konkretnego problemu, nie widzę tego tutaj, więc dodam taki, który właśnie wbijał mnie w mój post :
-Wformat=2
flagI naprawdę ważna część na ten temat ( zgodnie z instrukcją GCC ):
A więc to, że masz,
-Wall
nie oznacza, że masz wszystko. ;)źródło
Czasami używam
-s
do znacznie mniejszego pliku wykonywalnego:Źródło: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
źródło
strip
swój plik binarny, w ten sposób możesz mieć plik binarny z informacjami debugowania, a następnie usunąć go do dystrybucji.strip
też działa, ale-s
może być szybsze i łatwiejsze, chociaż nie jest tak wyszukane jak bieganiestrip
Chociaż ta odpowiedź może być nieco nie na temat, a pytanie jest godne +1 ode mnie, ponieważ
jest narzędzie, które powinno wychwycić WSZYSTKIE błędy i potencjalne błędy, które mogą nie być oczywiste, jest też szyna, której IMHO lepiej radzi sobie z wyłapywaniem błędów w porównaniu z gcc lub jakimkolwiek innym kompilatorem. To wartościowe narzędzie, które warto mieć w swojej skrzynce z narzędziami.Statyczne sprawdzanie za pomocą narzędzia typu lint, takiego jak szyna, powinno być częścią łańcucha narzędzi kompilatora.
źródło
Oprócz
-Wall
The-W
albo-Wextra
opcja (-W
współpracuje ze starszymi wersjami GCC, jak również nowsze; nowsze wersje obsługują alternatywną nazwę-Wextra
, co oznacza to samo, ale jest bardziej opisowy) umożliwia różne dodatkowe ostrzeżenia.Jest jeszcze więcej ostrzeżeń, które nie są włączane przez żadną z nich, generalnie dla rzeczy, które są bardziej wątpliwe. Zestaw dostępnych opcji zależy od używanej wersji gcc - skonsultuj
man gcc
lubinfo gcc
po szczegóły, albo zajrzyj do dokumentacji online dla konkretnej wersji gcc, którą jesteś zainteresowany. I wyświetla-pedantic
wszystkie ostrzeżenia wymagane przez konkretny używany standard (co zależy na innych opcjach, takich jak-std=xxx
lub-ansi
) i narzeka na użycie rozszerzeń gcc.-Werror
zamienia wszystkie ostrzeżenia w błędy. Nie sądzę jednak, aby gcc pozwalało na to selektywnie w przypadku określonych ostrzeżeń.Prawdopodobnie okaże się, że musisz selektywnie wybierać, które ostrzeżenia są włączone dla każdego projektu (zwłaszcza jeśli używasz
-Werror
), ponieważ pliki nagłówkowe z bibliotek zewnętrznych mogą powodować problemy z niektórymi z nich. (-pedantic
w szczególności wydaje mi się, że nie jest to pomocne w tym względzie, z mojego doświadczenia).źródło
-Werror=some-warning
.-Wmissing-prototypes
: Jeśli funkcja globalna jest zdefiniowana bez wcześniejszej deklaracji prototypu.-Wformat-security
: Ostrzega przed używaniem funkcji formatu, które stanowią potencjalne problemy z bezpieczeństwem. Obecnie ostrzega to o wywołaniachprintf
iscanf
funkcjach, w których ciąg formatu nie jest literałem ciągu i nie ma argumentów formatuźródło
-Werror=return-type
: Wymuś błąd, gdy funkcja nie zwraca w gcc. Jest/we4716
w Visual Studio.-Werror=implicit-function-declaration
: Wymuś błąd, gdy funkcja jest używana bez zdefiniowanej / nieuwzględnionej. Jest/we4013
w Visual Studio.-Werror=incompatible-pointer-types
: Oznacza błąd, gdy typ wskaźnika jest niezgodny z oczekiwanym typem wskaźnika. Jest/we4133
w Visual Studio.Właściwie chciałbym, aby mój kod w C był międzyplatformowy, używam CMake i umieszczam dostarczone cflagi w CMakeLists.txt w następujący sposób:
źródło