C için yararlı GCC bayrakları


157

Ayarlama -Wallve ayarlamanın ötesinde , -std=XXXC'de kullanmak için gerçekten yararlı, ancak daha az bilinen derleyici bayrakları var mı?

Özellikle ek uyarılarla ve / veya bazı durumlarda yanlışlıkla tür uyumsuzluklarını en aza indirmek için uyarıları hatalara dönüştürmekle ilgileniyorum.


9
Eh -save-temps, -Wshadowve -fmudflapben bilmiyordum büyük buluntular, herkese teşekkürler idi.
Matt Joiner

Bağlam, anlayabildiğim kadarıyla: gcc -c [flags-go-here] -o myprog.o myprog.cbir C programını derlemek (bağlamak değil) için çalışıyor.
Rory O'Kane

Yanıtlar:


64

Birkaç -fkod üretme seçenekleri ilginç:

  • -ftrapvFonksiyon programı işaretli tamsayı taşma (C resmen "tanımsız davranış") üzerine iptal olmasına neden olur.

  • -fverbose-asm ile derliyorsanız faydalıdır -S çıktısını incelemek için - bazı bilgilendirici yorumlar ekler.

  • -finstrument-functions her fonksiyon giriş ve çıkış noktasında kullanıcı tarafından sağlanan profil oluşturma işlevlerini çağırmak için kod ekler.


Çünkü -ftrapv, buraya bir göz atın stackoverflow.com/questions/20851061/… .. uzun bir süre düzeltilmek için bekleyen bir hata var gibi görünüyor.
Arjun Sreedharan

Yukarıdaki yorumu kontrol edebilir misiniz?
Suraj Jain

-ftrapv, aslında -fsanitize = işaretli tamsayı taşması ile değiştirildi.
Marc Glisse

139

İşte benim:

  • -Wextra, -Wall: gerekli.
  • -Wfloat-equal: faydalıdır, çünkü genellikle eşitlik için kayan nokta sayılarını test etmek kötüdür.
  • -Wundef: bir #ifdirektifte başlatılmamış bir tanımlayıcı değerlendirilirse uyar .
  • -Wshadow: bir yerel değişken başka bir yerel değişkeni, parametreyi veya genel değişkeni gölgelediğinde ya da yerleşik bir işlev gölgelendiğinde uyar.
  • -Wpointer-arith: bir şey bir işlevin veya boyutunun boyutuna bağlıysa uyar void.
  • -Wcast-align: işaretçi her kullanıldığında, hedefin gerekli hizalaması artırılacak şekilde uyar. Örneğin, a char *birint * tamsayılar sadece iki veya dört bayt sınırları adresinden ulaşılabilir makinelerde.
  • -Wstrict-prototypes: bir işlev argüman türlerini belirtmeden bildirilir veya tanımlanırsa uyar.
  • -Wstrict-overflow=5: derleyicinin imzalı taşma gerçekleşmediği varsayımına göre optimizasyon yaptığı durumlar hakkında uyarır. (5 değeri çok katı olabilir, kılavuz sayfasına bakın.)
  • -Wwrite-strings: dize sabitlerini tür const char[uzunluğunu verin, ]böylece adresinconst char * gösterici uyarı alır.
  • -Waggregate-return: yapıları veya sendikaları döndüren işlevler tanımlanırsa veya çağrılırsa uyar.
  • -Wcast-qual: hedef türden bir tür niteleyicisini kaldırmak için bir işaretçi kullanıldığında uyar * .
  • -Wswitch-default: bir switchifadede defaultdurum olmadığında uyar * .
  • -Wswitch-enum: bir switchifadede numaralandırılmış türden bir dizin olduğunda ve casebu numaralandırmanın adlandırılmış kodlarından biri veya daha fazlası için a olmadığında uyar * .
  • -Wconversion: bir değeri değiştirebilecek örtük dönüşümler için uyar * .
  • -Wunreachable-code: derleyici kodun hiçbir zaman yürütülmeyeceğini algılarsa uyar * .

* İşaretli olanlar bazen çok fazla sahte uyarı verir, bu yüzden onları gerektiği gibi kullanırım.


11
Oldukça eksiksiz bir liste, sadece bir tane daha eklemek istiyorum; -Wformat=2: Printf / scanf fonksiyonlarında ekstra format kontrolleri.
schot

1
Tüm bunlar ima etti -Wallmi?
chacham15

2
@ chacham15, hayır, sanmıyorum. gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Alok Singhal

1
@Alok hmm, belki de dağıtımlar arasında standart değil mi? Benim MBP üzerinde açıkça -Wwrite-stringsnefret ediyorum çünkü o kadar nefret ediyorum biliyorum.
chacham15

@ chacham15, belki. Ancak bunun açıklaması -Wwrite-stringsözellikle bunun bir parçası olmadığını söylüyor -Wall: gcc.gnu.org/onlinedocs/gcc/… . Belki kurulumunuzda başka bir şey bu bayrağı ayarlıyor olabilir mi? Ya da belki C ++ derliyorsunuz?
Alok Singhal

52

Her zaman kullanmak -O(yukarıda veya -O1, -O2,-Os vb.) Varsayılan optimizasyon düzeyinde, gcc derleme hızına gider ve birimleştirilmiş değişkenler gibi şeyler hakkında uyarmak için yeterli analiz yapmaz.

-WerrorDerlemeyi durdurmayan uyarılar göz ardı edilme eğiliminde olduğundan politika yapmayı düşünün .

-Wall hata olması muhtemel uyarıları hemen hemen açar.

Dahil edilen uyarılar -Wextragenel, geçerli kodu işaretleme eğilimindedir. (Tüysüz tarzı programlar çok daha fazla tuzak daha esnek bulmak olsa da) kod değerlendirmeleri için yararlı olabilir, ama normal gelişim için onları açmak olmaz.

-Wfloat-equal projedeki geliştiricilerin kayan noktaya aşina olmadığı iyi bir fikirdir ve eğer kötü bir fikirdir.

-Winit-selfkullanışlı; Neden dahil olmadığını merak ediyorum -Wuninitialized.

-Wpointer-arithçalışmayan çoğunlukla taşınabilir kodunuz varsa kullanışlıdır -pedantic.


9
+1 için "-Wfloat-equal, projedeki geliştiriciler kayan noktaya aşina değilse iyi bir fikirdir ve eğer kötü bir fikirdir." özellikle de ikinci yarısı. :-)
R .. GitHub DUR YARDIMCI ICE

39
-save-temps

Bu, önişlemci ve montajın sonuçlarını geride bırakır.

Önceden işlenmiş kaynak, hata ayıklama makroları için kullanışlıdır.

Montaj, hangi optimizasyonların yürürlüğe girdiğini belirlemek için kullanışlıdır. Örneğin, GCC'nin bazı özyinelemeli işlevlerde kuyruk çağrısı optimizasyonu yaptığını doğrulamak isteyebilirsiniz, çünkü onsuz yığını taşabilir.


Bunu nasıl yapacağınızı merak ettim ... İhtiyacım olursa her zaman gcc'den montajı boşaltmasını istedim.

35

Kimsenin bunu henüz söylemediğine şaşırdım - endişelendiğim kadarıyla en yararlı bayrak -g, hata ayıklama bilgisini yürütülebilir dosyaya koyan , böylece hata ayıklayabilmeniz ve kaynakta adım atmanızdır (eğer yetkin ve okuma meclisi değilseniz ve stepikomutu gibi ) bir program yürütürken.


35

-fmudflap - UB'yi yakalamak için tüm riskli işaretçi işlemlerine çalışma zamanı denetimleri ekler. Bu, programınızı tekrar arabellek taşmalarını etkili bir şekilde bağışıklık kazandırır ve her türlü sarkan işaretçi yakalamaya yardımcı olur.

İşte bir demo:

$ 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

Hmmm, çamurluk oldukça kötü görünüyor: P
Matt Joiner

9
-fmudflapGCC 4.9'dan bu yana artık desteklenmiyor warning: switch '-fmudflap' is no longer supported. Yerini AddressSanitizer aldı.
Agostino

21

Gerçekten C / C ++ ile ilgili değil, ama yine de yararlı:

@file

Yukarıdaki tüm iyi bayrakları (belirttiğiniz) bir 'dosyaya' koyun ve bu dosyadaki tüm bayrakları birlikte kullanmak için yukarıdaki bayrağı kullanın.

Örneğin:

Dosya: compilerFlags

-Duvar

-std = c99

-Wextra

Sonra derleyin:

gcc yourSourceFile @compilerFlags

15

-march=native derlemekte olduğunuz platform (= chip) için optimize edilmiş kod üretmek için


2
Hedefi bilmediğiniz yerel olmayan makineler için derliyorsanız, talimat setleri kullanmadan optimize eden mtune = xxx kullanabilirsiniz. Örneğin mtune = generic "ortalama" vaka işlemcileri ile güncel tutulur.
Turix

15

Derleyici tarafından önceden tanımlanmış önişlemci bayraklarını bilmeniz gerekiyorsa:

echo | gcc -E -dM -

13

Hataları tespit etmek için gerçekten yararlı değil, ancak nadiren belirtilen -masm=intelseçenek-S montaj çıktısını çok daha güzel incelemek için sağlar.

AT&T montaj sözdizimi kafamı çok fazla acıtıyor.


2
AT&T ve Intel arasındaki fark C # ve Java arasındaki farktır. Sadece sözdizimi. Her ikisi de korkunç. :)
Matt Joiner

2
+1 @michael, gcc'yi tanrı yerine intel sözdizimini kullanarak & t. Montajı denetlemek için yeterli beyin döngüsü kullanılır - src'nin opcodlarda dest'den önce gittiği beyin döngülerini boşa harcamasına gerek yoktur. Şimdi sadece gcc, diğer derleyiciler gibi __asm ​​{} satır içi özelliğini destekliyorsa, hepimiz hazırız!
greatwolf

10

Dosyam genellikle

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

Bu seçeneklerden en önemlisi daha önce tartışılmıştır, bu yüzden henüz işaret edilmeyen iki özelliğe dikkat çekeceğim:

Ben hala iyi bir C ++ derleyici olan bazı platforma taşınabilirlik için düz C olması gereken bir kod temeli üzerinde çalışmama rağmen , (C derleyici ek olarak) C ++ derleyicisi ile bir "ekstra" derleme yapmak. Bunun 3 faydası vardır:

  1. C ++ derleyicisi bazen C derleyicisinden daha iyi uyarı mesajları verir.
  2. C ++ derleyicisi, bazen düz C'de derlediğimde kaçırdığım bazı yararlı ipuçları veren -Weffc ++ seçeneğini kabul eder.
  3. Ben kodu düz C kodu geçersiz C ++ kodu ("bool" adlı bir değişken tanımlamak gibi) olduğu birkaç sınır koşullardan kaçınarak, C ++ bağlantı noktası nispeten kolay tutabilir.

Evet, umutsuzca iyimser bir Pollyanna, kesinlikle bir ayın artık bir platformun eski olarak ilan edileceğini veya iyi bir C ++ derleyicisi kazanacağını düşünmeye devam ediyor ve sonunda C ++ 'ya geçebiliriz. Aklımda, kaçınılmaz - tek soru bunun yönetimden önce veya sonra nihayet herkese midilli verip vermeyeceği. :-)


C ++ olarak yazmanın iyi bir noktası, bunu sık sık düşünüyorum. (doğal olarak alt küme)
Matt Joiner

6
C ++ 'ın lehine kullanımdan kaldırıldığına hiç dikkat etmeyeceğim, üzgünüm :)
Matt Joiner

4
rm yerine -o / dev / null düşünün -f önemsiz
ulidtko

9
-Wstrict-prototypes -Wmissing-prototypes

10
Ve -Wold-style-definitioneğer K&R stil fonksiyonlarının prototipli beyanlarda bile iyi bir fikir olduğunu düşünen recidivistlerle uğraşmak zorundaysanız. (Böyle insanlarla uğraşmak zorundayım. K & R'de yazılmış yeni bir kod bulduğumda gerçekten canımı sıkıyor. Sabit olmayan eski K&R şeylerine sahip olmak yeterince kötü, ama yeni kod! Grump !!!)
Jonathan Leffler

9

Bahsetilmeyen harika bir bayrak:

-Werror-implicit-function-declaration

Bir işlev bildirilmeden önce her kullanıldığında bir hata verin.


8
man gcc

Kılavuz, iyi açıklamalara sahip ilginç bayraklarla doludur. Ancak, -Wall muhtemelen gcc'yi mümkün olduğunca ayrıntılı yapacaktır. Daha ilginç veriler istiyorsanız, hataları kontrol etmek için valgrind veya başka bir araca bakmalısınız.


1
Gerçi loooooooooooooooooooooooooooooooong olduğunu. man gcc | nl11000 satır üzerinden raporlar. Bu rezil bashmanpageden daha fazlası !
yeni123456

12
Şükürler olsun ki, bu devasa gezilemez "bilgi" sayfalarından biri yerine, onu bir man sayfasına sıkıştırdılar.
Matt Joiner

6

Eh, -Wextrastandart da olmalı. -Werroruyarıları hatalara dönüştürür (özellikle de derlemezseniz çok can sıkıcı olabilir -Wno-unused-result). -pedanticile bütünlüğündestd=c89 kullanıldığında, C99 özelliklerini kullanıyorsanız ek uyarılar verir.

Ama bu kadar. Bir C derleyicisini C'nin kendisinden daha fazla tür tasarruflu bir şeye ayarlayamazsınız.


6

-M* seçenekler ailesi.

Bunlar, c veya c ++ kaynak dosyalarınızın hangi başlık dosyalarını kullanması gerektiğini otomatik olarak anlayan make dosyaları yazmanıza izin verir. GCC, bu bağımlılık bilgileriyle make dosyaları oluşturur ve daha sonra bunları birincil make dosyanızdan dahil edersiniz.

İşte c ++ kaynak ve başlık dosyalarıyla dolu bir dizini derleyecek ve tüm bağımlılıkları otomatik olarak çözecek -MD ve -MP kullanan son derece genel bir makefile örneği:

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

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

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

İşte daha ayrıntılı olarak tartışan bir blog yazısı: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html


6

Orada -Werrorhata olarak tüm uyarıları davranır ve derleme durur ki,. gccManuel sayfa derleyici için her komut satırı anahtarını açıklıyor.


@Matt Joiner: Hangi makine mimarisini kullandığınızdan bahsetmediğiniz için, gccbayraklar sizinkiyle kimsenin önerebileceği herhangi bir bağlantı arasında farklı olabilir. Bu nedenle yazılımınızla birlikte manuel sayfalar sağlanır.
Greg Hewgill

4

-Wfloat-equal

Gönderen: http://mces.blogspot.com/2005/07/char-const-argv.html

Sevdiğim diğer yeni uyarılardan biri -Wfloat-eşittir. Bu, eşitlik koşulunda kayan noktalı bir sayıya sahip olduğunuzda uyarır. Bu harika! Her biri bir bilgisayar grafiği veya (daha kötüsü :) hesaplamalı geometri algoritması programladıysanız, hiçbir şamandıranın eşitlikle eşleşmediğini bilirsiniz ...


10
Benim yüzer yok ben ne yaptığımı biliyorum, eşitlik ile eşleşecek.
Roland Illig

4

Bu konuyu belirli bir sorunu düzeltmek için bir bayrak arıyor buldum, burada görmüyorum, bu yüzden sadece yazıma beni çarpıyor bir tane ekleyeceğim :

-Wformat=2bayrak

-Wformat=> Sağlanan bağımsız değişkenlerin belirtilen biçim dizesine uygun türlere sahip olduğundan emin olmak için printfve scanfvb. Çağrılarını kontrol edin ...

Ve bununla ilgili gerçekten önemli kısım ( GCC kılavuzuna göre ):

-Wformatdahil -Wall. Seçenekleri işaretleyerek biçimi bazı yönleri üzerinde daha fazla denetim sağlamak için -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, ve -Wformat=2kullanılabilir, ancak -Wall.` dahil değildir

Yani, sadece sahip -Wallolmanız her şeye sahip olduğunuz anlamına gelmez. ;)


3

Bazen -sçok daha küçük bir yürütülebilir dosya için kullanıyorum:

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

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


6
sadece stripikili dosya üzerinde çalıştırmalısınız , bu şekilde hata ayıklama bilgilerine sahip bir ikili dosyaya sahip olabilir, dağıtım için daha sonra kaldırabilirsiniz.
Hasturkun

Evet, stripçalışıyor ama -sdaha hızlı ve daha kolay olabilir, ancak koşmak kadar ayrıntılı olmasa dastrip
Vasiliy Sharapov

3

Bu cevap biraz konu dışı olabilir ve soru benden değerli bir +1 olsa da,

Özellikle ek uyarılarla ve / veya bazı durumlarda yanlışlıkla tür uyumsuzluklarını en aza indirmek için uyarıları hatalara dönüştürmekle ilgileniyorum.
TÜM hataları ve belirgin olmayan potansiyel hataları yakalaması gereken bir araç var, IMHO'nun gcc veya bu konudaki herhangi bir derleyiciye kıyasla hataları yakalamada daha iyi bir iş yaptığı ateli var . Bu, alet göğsünüzde bulunmaya değer bir araçtır.

Atel gibi tüy bırakmayan bir aletle statik kontrol, bir derleyici alet zincirinin parçası olmalıdır.


Her zaman bir hata C: \ include önişlemci dosyası dosyalayamaz gösterir, ne yapacağımdan emin değilim
Suraj Jain

2

Özellikle ek uyarılarla ilgileniyorum,

Buna ek olarak -Wall, -Wveya -Wextraseçeneği ( -Wgcc'nin eski sürümleriyle ve daha yeni sürümlerle çalışır; daha yeni sürümler alternatif adı destekler -Wextra, bu aynı şey anlamına gelir, ancak daha açıklayıcıdır) çeşitli ek uyarılar sağlar.

Bunların hiçbiri tarafından etkinleştirilmeyen daha genel uyarılar da vardır, bunlar genellikle daha kötü olan şeyler için. Kullanılabilir seçenekler kümesi kullandığınız gcc sürümüne bağlıdır - danışmak man gccveya info gccayrıntılar için veya ilgilendiğiniz belirli gcc sürümü için çevrimiçi belgelere bakın . Ve -pedantickullanılan belirli standart için gerekli olan tüm uyarıları (buna bağlı olarak değişir) -std=xxxveya -ansi) gibi diğer seçeneklerde ve gcc uzantılarının kullanımı hakkında şikayette bulunur.

ve / veya kazara tipteki yanlış eşleşmeleri kesinlikle en aza indirmek için bazı durumlarda uyarıları hatalara dönüştürmek.

-Werrortüm uyarıları hataya dönüştürür. Bununla birlikte, gcc'nin belirli uyarılar için bunu seçici bir şekilde yapmanıza izin verdiğini sanmıyorum.

-WerrorHarici kitaplıklardan başlık dosyaları bazılarını açabileceğinden, muhtemelen proje başına (özellikle kullanıyorsanız ) hangi uyarıların etkinleştirildiği konusunda seçici olmanız gerektiğini göreceksiniz . ( -pedanticözellikle benim deneyimime göre bu konuda yararsız olma eğilimindedir.)


4
"Gcc'nin bunu belirli uyarılar için seçici olarak yapmasına izin verdiğini sanmıyorum." Aslında, ile yapabilirsiniz -Werror=some-warning.
Matthew Flaschen

0
  • -Wmissing-prototypes: Genel bir işlev önceden bir prototip bildirimi olmadan tanımlanmışsa.
  • -Wformat-security: Olası güvenlik sorunlarını temsil eden format işlevlerinin kullanımı hakkında uyarır. Şu anda bu , biçim dizesinin bir dize değişmezi olmadığı ve biçim bağımsız değişkenlerinin olmadığı çağrılara printfve scanfişlevlere karşı uyarır.

0
  • -Werror=return-type: Fonksiyonun gcc'de dönüşü olmadığında hatayı uygula. Öyle /we4716Visual Studio.

  • -Werror=implicit-function-declaration: İşlev tanımlanmadan / dahil edilmeden kullanıldığında hatayı uygulayın. Öyle /we4013Visual Studio.

  • -Werror=incompatible-pointer-types: Bir işaretçi türü beklenen işaretçi türüyle eşleşmediğinde hata oluşmasını önler. Öyle /we4133Visual Studio.

Aslında, C kodumu çapraz platformda tutmak istiyorum ve CMake kullanıyorum ve sağlanan cflags'ı CMakeLists.txt'ye koydum:

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()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.