Kapsamlı ve ayrıntılı g ++ uyarılarını etkinleştirmek için işaretler


122

Genellikle C altında gcc, aşağıdaki uyarı bayrakları kümesiyle başlayacağım (birden çok kaynaktan acı verici bir şekilde bir araya getirilmiş):

-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

Bu uyarı setiyle (en azından hata ayıklama sürümlerimi) oluşturacağım ve yapabileceğim her şeyi (genellikle her şeyi) düzelteceğim ve sonra bayrakları yalnızca ilgili değillerse veya düzeltilemezlerse kaldıracağım (neredeyse hiçbir durumda). Bazen -Werrorderleme sırasında bir adım atmam gerekip gerekmediğini de ekleyeceğim .

Sadece C ++ 'yı alıyorum (evet, zamanın 15 yıl gerisindeyim) ve doğru ayakla başlamak istiyorum.

Sorum şu: Birisinin altında C ++ için önceden derlenmiş benzer tam uyarı bayrakları var g++mı? (Birçoğunun aynı olacağını biliyorum.)


69
Ne (o pervasızca karar beri gcc ihtiyaçları yalan hakkında -Wall) bir olan -Wbloody_everythingbayrak :-)
paxdiablo

Sorunuzu dupe olarak işaretleyebilirsiniz, ancak sorunuzu gerçekten yanıtladığınız için son düzenlemenizi de yanıt olarak koyabilirsiniz. Ve o zaman buna olumlu oy vermekten memnuniyet duyarım :)
ereOn

4
OP ve @paxdiablo: GCC bu tür şeyleri sürekli olarak reddetti , ancak Clang aracılığıyla kullanılabilir -Weverything. Clang ++ geliştiricilerinin bile kullanıcıların onu açması konusunda biraz endişeli olduklarını okudum; görünüşe göre yalnızca dahili geliştirme kullanımı için tasarlanmıştı. Yine de bu mantıklı değil, çünkü açmak -Weverythingmuhtemelen daha önce bilmediğiniz potansiyel olarak yararlı uyarıları keşfetmenin en olası yoludur.
Kyle Strand

1
OP ve @paxdiablo Belirli bir GCC sürümü için uyarıların tam listesini bulmanın artık bir yolu var: github.com/barro/compiler-warnings
Kyle Strand

Yanıtlar:


138

İnceledim ve maksimum uyarı seviyesini alması gereken minimum içerik grubunu buldum. Daha sonra bu listeden, aslında kötü bir şey olduğunu göstermediğini ya da gerçek bir yapıda kullanılacak çok fazla yanlış pozitif olduğunu düşündüğüm uyarıları çıkardım. Hariç tuttuğum her birinin neden dışlandığını yorumladım. Bu, önerilen son uyarı grubum:

-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

Mevcut şüpheli uyarılar:

  • Ekliyorum -Wno-unusedçünkü daha sonra kullanacağımı bildiğim, ancak henüz işlevsellik için yazılmamış değişkenlerim var. Bununla ilgili uyarıları kaldırmak, zaman zaman şeylerin uygulanmasını erteleyerek tercih ettiğim tarzda yazmama izin veriyor. Çatlaklardan hiçbir şeyin kaymadığından emin olmak için bunu arada bir kapatmak yararlıdır.

  • -Wdisabled-optimizationgüçlü bir kullanıcı tercihi ayarı gibi görünüyor. Bunu henüz yapıma ekledim (yalnızca bariz nedenlerden dolayı optimize edilmiş yapılar için) ve hiçbir şey ortaya çıkmadı, bu yüzden en azından kodlama şeklim için özellikle konuşkan bir uyarı gibi görünmüyor. Onu ekliyorum (bu uyarıyı tetikleyen kod mutlaka yanlış olmasa da) çünkü onlara karşı değil de araçlarımla çalışmaya inanıyorum. Gcc bana kodu yazma şeklim için optimize edemeyeceğini söylüyorsa, yeniden yazmaya bakmalıyım. Bu uyarıyı tetikleyen kodun, ne olursa olsun daha modüler olmasından fayda sağlayacağından şüpheleniyorum, bu nedenle kod teknik olarak yanlış olmasa da (muhtemelen), biçimsel olarak muhtemelen öyle.

  • -Wfloat-equalgüvenli eşitlik karşılaştırmaları için uyarır (özellikle hesaplanmamış -1 değeriyle karşılaştırma). Kodumda bunu kullandığım bir örnek, bir float vektörümün olmasıdır. Bu vektörün üzerinden geçiyorum ve henüz ne olmaları gerektiğini değerlendiremediğim bazı öğeler var, bu yüzden onları -1.0f olarak ayarlıyorum (benim problemim sadece pozitif sayılar kullandığından, -1 alan dışında kalıyor). Daha sonra -1.0f değerlerini gözden geçirip güncelliyorum. Kendini farklı bir operasyon yöntemine kolayca ödünç vermez. Çoğu insanın bu sorunu yaşamadığından şüpheleniyorum ve kayan noktadaki kesin bir sayının karşılaştırılması muhtemelen bir hatadır, bu yüzden varsayılan listeye ekliyorum.

  • -Wold-style-castkullandığım kütüphane kodunda çok sayıda yanlış pozitif var. Özellikle, ağ oluşturmada kullanılan htonl işlev ailesi ve kullandığım bir Rijndael (AES) şifreleme uygulaması, beni uyaran eski tarz yayınlara sahip. Bunların ikisini de değiştirmek niyetindeyim, ancak kodumda şikayet edecek başka bir şey olup olmadığından emin değilim. Yine de çoğu kullanıcı muhtemelen bunu varsayılan olarak açmalıdır.

  • -Wsign-conversionzordu (ve neredeyse listeyi yapamadı). Kodumda açmak büyük miktarda uyarı oluşturdu (100+). Neredeyse hepsi masumdu. Bununla birlikte, emin olmadığım yerlerde işaretli tam sayıları kullanmaya özen gösterdim, ancak özel sorun alanım için, yaptığım büyük miktarda tamsayı bölümü nedeniyle genellikle işaretsiz değerleri kullanarak küçük bir verimlilik artışı elde ederim. Bu verimliliği feda ettim çünkü işaretli bir tamsayıyı yanlışlıkla işaretsiz bir sayıya yükseltmek ve sonra bölmekle ilgileniyordum (toplama, çıkarma ve çarpmanın aksine güvenli değil). Bu uyarıyı açmak, değişkenlerimin çoğunu güvenli bir şekilde işaretsiz türlere dönüştürmeme ve başka yerlerde birkaç yayın eklememe izin verdi. Şu anda kullanmak biraz zor çünkü uyarı o kadar akıllıca değil. Örneğin, yaparsanunsigned short + (integral constant expression), bu sonuç dolaylı olarak int'e yükseltilir. Daha sonra, bu değeri unsignedveya unsigned shortgüvenli olsa bile, bu değeri atarsanız olası bir işaret problemi hakkında uyarır . Bu, neredeyse tüm kullanıcılar için kesinlikle en isteğe bağlı uyarıdır.

  • -Wsign-promo: bkz -Wsign-conversion.

  • -Wswitch-defaultanlamsız görünüyor (tüm olasılıkları açıkça sıraladıysanız her zaman varsayılan bir durum istemezsiniz). Ancak, bu uyarıyı açmak, muhtemelen iyi bir fikir olan bir şeyi zorunlu kılabilir. Listelenen olasılıklar dışındaki her şeyi açıkça görmezden gelmek istediğiniz durumlar için (ancak başka sayılar mümkündür), sonradefault: break;açık hale getirmek için. Tüm olasılıkları açık bir şekilde sıralarsanız, bu uyarıyı açmak, tüm olası seçenekleri gerçekten kapladığınızdan emin olmak için assert (false) gibi bir şey koymanıza yardımcı olacaktır. Sorununuzun etki alanında açık olmanızı sağlar ve bunu programatik olarak uygular. Ancak, her yerde iddia (yanlış) yaparken dikkatli olmalısınız. Varsayılan durumla hiçbir şey yapmamaktan daha iyidir, ancak her zamanki gibi assert'te olduğu gibi sürüm sürümlerinde çalışmaz. Diğer bir deyişle, üzerinde mutlak kontrole sahip olmadığınız bir ağ bağlantısından veya veritabanından aldığınız numaraları doğrulamak için ona güvenemezsiniz. İstisnalar veya erken dönüş, bunun üstesinden gelmenin en iyi yoludur (ancak yine de varsayılan bir vakaya sahip olmanızı gerektirir!).

  • -Werrorbenim için önemli. Birden çok hedefe sahip çok iş parçacıklı bir yapıda büyük miktarda kod derlerken, bir uyarının geçmesi kolaydır. Uyarıları hatalara dönüştürmek, onları fark etmemi sağlar.

Sonra, yararlı bulmadığım için yukarıdaki listede yer almayan bir dizi uyarı var. Bunlar, neden onları varsayılan listeye dahil etmediğime dair uyarılar ve yorumlarım:

Eksik uyarılar:

  • -Wabigerekli değil çünkü farklı derleyicilerden ikili dosyaları birleştirmiyorum. Yine de onunla derlemeyi denedim ve tetiklenmedi, bu yüzden gereksiz yere ayrıntılı görünmüyor.

  • -Waggregate-returnhata olduğunu düşündüğüm bir şey değil. Örneğin, bir sınıf vektörü üzerinde aralık tabanlı bir for döngüsü kullanıldığında tetiklenir. Geri dönüş değeri optimizasyonu, bunun herhangi bir olumsuz etkisine dikkat etmelidir.

  • -Wconversionbu kodda tetikler: short n = 0; n += 2;int'e örtük dönüştürme, daha sonra hedef türüne geri dönüştürüldüğünde bir uyarıya neden olur.

  • -Weffc++başlatıcı listesinde tüm veri üyeleri başlatılmazsa bir uyarı içerir. Bunu pek çok durumda kasıtlı olarak yapmıyorum, bu nedenle uyarılar yararlı olamayacak kadar karışıktır. Arada bir açmak ve diğer uyarıları taramak (temel sınıfların sanal olmayan yıkıcıları gibi) yararlıdır. Bu -Wall, kendi başına tek bir uyarı yerine bir uyarılar koleksiyonu (gibi ) olarak daha yararlı olacaktır .

  • -Winlinesatır içi anahtar kelimesini optimizasyon amacıyla kullanmıyorum, sadece başlıklarda işlevleri satır içi olarak tanımlamak için kullanıyorum. İyileştiricinin gerçekten satır içinde olması umurumda değil. Bu uyarı, bir sınıf gövdesinde (boş bir sanal yıkıcı gibi) bildirilen bir işlevi satır içine alamadığından da şikayet eder.

  • -Winvalid-pch eksik çünkü önceden derlenmiş üstbilgiler kullanmıyorum.

  • -Wmissing-format-attributegnu uzantılarını kullanmadığım için kullanılmıyor. Aynı -Wsuggest-attributeve diğerleri için

  • Muhtemelen yokluğuyla dikkate değer -Wno-long-long, ki buna ihtiyacım yok. Tam sayı türlerini içeren -std=c++0x( -std=c++11GCC 4.7'de) ile derliyorum long long. C ++ 98 / C ++ 03'e takılanlar, bu dışlamayı uyarı listesinden eklemeyi düşünebilir.

  • -Wnormalized=nfc zaten varsayılan seçenektir ve en iyisi gibi görünüyor.

  • -Wpaddedsınıfların düzenini optimize etmek için ara sıra açılır, ancak tüm sınıfların sonunda dolguyu kaldırmak için yeterli öğeye sahip olmadığı için açık bırakılmaz. Teoride 'ücretsiz' olarak bazı ekstra değişkenler alabilirim, ancak bunu sürdürmek için fazladan çabaya değmez (sınıf boyutum değişirse, bu önceden serbest değişkenleri kaldırmak kolay değildir).

  • -Wstack-protector kullanılmıyor çünkü kullanmıyorum -fstack-protector

  • -Wstrict-aliasing=3tarafından açılır -Wallve en doğru olanıdır, ancak 1. ve 2. düzey daha fazla uyarı veriyor gibi görünüyor. Teoride daha düşük bir seviye 'daha güçlü' bir uyarıdır, ancak daha yanlış pozitiflere mal olur. Kendi test kodum 3 seviyenin tamamında temiz bir şekilde derlendi.

  • -Wswitch-enumistediğim davranış değil. Her switch ifadesini açıkça işlemek istemiyorum. Dilin, bunu belirtilen anahtar deyimlerinde etkinleştirmek için bir mekanizmaya sahip olması yararlı olabilir (numaralandırmada gelecekteki değişikliklerin olması gereken her yerde işlenmesini sağlamak için), ancak "ya hep ya hiç" ayarı için aşırıdır.

  • -Wunsafe-loop-optimizationsçok fazla sahte uyarıya neden olur. Bunu periyodik olarak uygulamak ve sonuçları manuel olarak doğrulamak faydalı olabilir. Örnek olarak, bir vektördeki tüm öğeleri onlara bir dizi işlev uygulamak için (aralık tabanlı for döngüsünü kullanarak) döngü yaptığımda kodumda bu uyarıyı oluşturdu. Ayrıca, const std :: string dizisinin yapıcısı için de uyarıdır (burada bu, kullanıcı kodunda döngü değildir).

  • -Wzero-as-null-pointer-constantve -Wuseless-castGCC 4.7'ye geçiş yaptığımda ekleyeceğim yalnızca GCC-4.7 uyarılarıdır.

Bu araştırmanın bir kısmının sonucu olarak gcc'ye birkaç hata raporu / geliştirme isteği gönderdim, bu nedenle sonunda "dahil etme" listesinden "dahil etme" listesine daha fazla uyarı ekleyebileceğimi umuyorum. . Bu liste, bu başlıkta bahsedilen tüm uyarıları içerir (artı birkaç ekstra olduğunu düşünüyorum). Bu yazıda açıkça belirtilmeyen uyarıların çoğu, bahsettiğim başka bir uyarının parçası olarak dahil edilmiştir. Herhangi biri bu gönderinin tamamen dışında bırakılan herhangi bir uyarıyı fark ederse, bana bildirin.

düzenleme: Görünüşe göre birkaçını kaçırdım (şimdi ekledim). Aslında http://gcc.gnu.org adresinde oldukça iyi gizlenmiş ikinci bir sayfa var . Genel uyarı seçenekleri ve C ++ seçenekleri (uyarılar için aşağı kaydırın)


Yakın zamanda bu yanıt için yaptığım araştırmaya dayalı olarak bir geliştirme isteği gönderdim: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Uyarı seviyeleri oluşturarak uyarı durumunu önemli ölçüde basitleştirecektir. Benim önerimde, önerilen uyarı setim yaklaşık -W4 ve -Winf oluşturmak için ek bir teklifle birlikte, bu da -Her şey-ve-gerçekten-bunu-bu sefer-demek istiyorum
David Stone

-Wpadded'in bir kısmının önerilen listeye eklenmesine neden olacak geliştirme isteği: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone

-Weffc ++ bölümlerinin önerilen listeye eklenmesine neden olacak geliştirme isteği: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone

1
@Predelnik: Bundan daha zor. -Wswitch-enumbir anahtardaki her numaralandırma değerini açıkça işlemezseniz ve defaultaçık olarak sayılmazsa uyarır . Öte yandan, tüm olası değerleri açıkça ele almış olsanız bile -Wswitch-default, anahtarınızın bir defaultdurumu yoksa sizi uyarır .
David Stone

2
BTW - tüm bu yanlış pozitifleri önlemek için "eski kütüphane kodu" -isystemyerine kullanın-I
galois

39

D'oh, tüm orijinal aramalarım, uyarıların nasıl bastırılacağına dair gönderilerin% 99'unu ortaya çıkardı (yeterince korkutucu), ancak bu sevimli bayrak kümesine sahip olan (bazıları daha az alakalı) bu yoruma rastladım :

Çapraz kontrol edildi:

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

Bu yüzden bunun iyi bir başlangıç ​​noktası olduğunu düşünüyorum. Bunun bir aldatmaca olduğunu fark etmemiştim, ama en azından derine gömülmüştü. :-)


1
Belki, ama bu sürümler arasında ve muhtemelen güneş lekeleri ve RMS'nin hevesine göre değişiyor gibi görünüyor, bu yüzden aşırı açık olmak muhtemelen zarar vermeyecek. Zaten bu iyi bir başlangıç ​​noktası.
Sdaz MacSkibbons

3
4.5.2'nin 'OPT_W durumu' için c-opts.c / opts.c'nin hızlı bir grepinden, eksiksiniz: katı taşma, undef, katı nul sentinel, normalleştirilmiş, çok kanallı, örtük işlev bildirimi, kullanımdan kaldırılmış, endif etiketleri, yorum s , yerleşik makro yeniden tanımlandı, daha büyük, eq'den daha büyük, abi. Bunları listelemek için bir komut satırı seçeneğinin olmaması çılgınca.
Tony Delroy

3
Bence -Wallbirinin beklediğini yapmaması daha çılgınca . Ama teşekkürler, bunlardan bazıları çok faydalı görünüyor!
Sdaz MacSkibbons

1
Uyarıları etkisiz hale getirmenin yeri vardır. Sonuçta bunlar "uyarılar" dır. Diğer bir durum, birden fazla uyarıyı etkinleştiren bir bayrağı etkinleştirdiğinizde, ancak bu konuda seçici olmak istemenizdir.
Tamás Szelei

1
Nasıl kullanabiliyorsun -Waggregate-return? Bu bana her kullanım için bir uyarı veriyorbegin/end()
Flamefire

13

Bunlardan bazıları zaten -Wallveya içine dahil edilmiştir -Wextra.

C için iyi bir temel kurulum:

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

ve C ++ için

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

( -WerrorC ++ için atlamak -Weffc++bazı sıkıntılara sahiptir)


10
-Werror, belirli uyarı türleri için devre dışı bırakılabilir, örneğin: -Werror -Weffc ++ -Wno-error = effc ++
Robert Hensing

2
ansi : C modunda, bu eşdeğerdir -std=c89. C ++ modunda -std=c++98,. yani başka bir şey belirtiyorsanız std, kullanmayınansi
Sean Breckenridge

2

Deneyin

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

Bu hızlı ve kirli bir başlangıçtır ve kesinlikle biraz ayarlama gerektirecektir; Öncelikle, derleyiciyi dilinize uygun adla çağırsanız bile (örneğin g++C ++ için), o dil için geçerli olmayan uyarılar alırsınız (ve derleyici ellerini kaldırır ve siz gelene kadar devam etmeyi reddeder) uyarıyı kaldırın).

Başka bir şey de eklemem -Werror, çünkü uyarıları düzeltmiyorsanız, neden onları açmayı düşünüyorsunuz? Listeden uyarılar da alabilirsiniz. (Örneğin, -Waggregate-returnC ++ ile neredeyse hiç kullanmıyorum .)

Performansla ilgili diğer seçenekler ( -Wstack-protector) olmadan bazı uyarılar hiçbir şey yapmaz . -fdiagnostics-show-optionve GCC kılavuzu arkadaşlarınızdır.

Bu arada, bazı uyarılar birbirini dışlar; özellikle kullanmak -Wtraditionalve -Wold-style-definitionbirlikte -Werror, derlenmez.


0

Clion's CmakeLists.txt dosyamda

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)
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.