簡體   English   中英

用於啟用詳盡且詳細的g ++警告的標志

[英]Flags to enable thorough and verbose g++ warnings

通常在gcc下的C語言中,我將從以下一組警告標志開始(從多個來源痛苦地組裝):

-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年),我想從右腳開始。

我的問題是:在g++下,是否有人為C ++預編譯了一組類似的完整警告標志? (我知道其中很多都是一樣的。)

我經歷了一個最小的包含,它應該得到最高級別的警告。 然后我從該列表中刪除了一組警告,我覺得這些警告實際上並沒有表明發生了什么不好的事情,或者在實際構建中使用了太多的誤報。 我評論為什么我排除的每一個都被排除在外。 這是我最后一組建議的警告:

-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。 然后,如果您將該值分配給unsignedunsigned short ,即使它是安全的,它會警告潛在的符號問題。 對於幾乎所有用戶來說,這絕對是最可選的警告。

  • -Wsign-promo :請參閱-Wsign-conversion

  • -Wswitch-default似乎毫無意義(如果你明確列舉了所有可能性,你並不總是想要一個默認情況)。 但是,打開此警告可以強制執行一些可能是個好主意的事情。 對於您明確要忽略除列出的可能性之外的所有內容(但可能有其他數字)的情況,請輸入default: break; 使其明確。 如果您明確列舉了所有可能性,那么打開此警告將有助於確保您輸入類似assert(false)的內容以確保您實際涵蓋了所有可能的選項。 它可以讓您明確問題的域名並以編程方式強制執行。 但是,你必須要小心,只是在任何地方堅持斷言(假)。 它比默認情況下無所作為更好,但與assert一樣,它在發布版本中不起作用。 換句話說,您不能依賴它來驗證您從網絡連接或您無法完全控制的數據庫中獲得的數字。 例外或早退是處理這種情況的最佳方法(但仍需要你有一個默認情況!)。

  • -Werror對我來說, -Werror是一個重要的錯誤。 在具有多個目標的多線程構建中編譯大量代碼時,很容易發出警告。 將警告轉換為錯誤可確保我注意到它們。

然后有一組警告沒有包含在上面的列表中,因為我沒有發現它們有用。 這些是警告和我對我為什么不將它們包含在默認列表中的評論:

沒有警告:

  • -Wabi不需要因為我沒有組合來自不同編譯器的二進制文件。 無論如何我試着用它進行編譯,它沒有觸發,所以它似乎並不是不必要的冗長。

  • -Waggregate-return不是我認為是錯誤的東西。 例如,它在類向量上使用基於范圍的for循環時觸發。 返回值優化應該考慮到這種負面影響。

  • -Wconversion觸發此代碼: short n = 0; n += 2; short n = 0; n += 2; 隱式轉換為int會在將其轉換回目標類型時發出警告。

  • -Weffc++包含一個警告,如果所有數據成員都沒有在初始化列表中初始化。 在很多情況下我故意不這樣做,所以警告的集合太雜亂而無用。 不過,偶爾打開一次並掃描其他警告(例如基類的非虛擬析構函數)是有幫助的。 這將作為一組警告(如-Wall )而不是單獨的警告更有用。

  • -Winline不存在,因為我沒有使用inline關鍵字進行優化,只是為了在頭文件中內聯定義函數。 我不在乎優化器是否實際內聯它。 如果它不能內聯在類體(例如空虛擬析構函數)中聲明的函數,則此警告也會抱怨。

  • -Winvalid-pch缺失,因為我不使用預編譯頭。

  • -Wmissing-format-attribute未使用,因為我不使用gnu擴展名。 對於-Wsuggest-attribute和其他幾個相同

  • 它缺席的潛在值得注意的是-Wno-long-long ,這是我不需要的。 我使用-std=c++0x-std=c++11在GCC 4.7中)進行編譯,其中包括long long整數類型。 那些停留在C ++ 98 / C ++ 03上的人可能會考慮從警告列表中添加該排除。

  • -Wnormalized=nfc已經是默認選項,看起來是最好的。

  • -Wpadded偶爾會打開,以優化類的布局,但它不會保留,因為並非所有類都有足夠的元素來刪除最后的填充。 從理論上講,我可以為“免費”獲得一些額外的變量,但是不值得花費額外的努力(如果我的班級大小發生變化,那么刪除那些以前的自由變量並不容易)。

  • -Wstack-protector未使用,因為我不使用-fstack-protector

  • -Wstrict-aliasing=3-Wall打開並且是最准確的,但它看起來像1級和2級提供更多警告。 從理論上講,較低的水平是一個“更強”的警告,但它的代價是更多的誤報。 我自己的測試代碼在所有3個級別下干凈地編譯。

  • -Wswitch-enum不是我想要的行為。 我不想明確處理每個switch語句。 如果語言有一些機制可以在指定的switch語句上激活它(以確保枚舉的未來更改可以在他們需要的任何地方處理),這將是有用的,但是對於“全有或全無”設置來說是過度的。

  • -Wunsafe-loop-optimizations導致過多的虛假警告。 定期應用此方法並手動驗證結果可能很有用。 例如,當我遍歷向量中的所有元素以將一組函數應用於它們時(使用基於范圍的for循環),它在我的代碼中生成了此警告。 它還警告const const std :: string的const數組的構造函數(其中這不是用戶代碼中的循環)。

  • -Wzero-as-null-pointer-constant-Wuseless-cast是僅GCC-4.7警告,我將在轉換到GCC 4.7時添加。

由於這項研究的結果,我已經在gcc上提交了一些錯誤報告/增強請求,所以希望我最終能夠將“不包含”列表中的更多警告添加到“包含”列表中。 此列表包含此主題中提到的所有警告(另外我還要考慮一些額外的警告)。 本文中未明確提及的許多警告都包含在我提到的另一個警告的一部分中。 如果有人注意到完全被排除在此帖之外的任何警告,請告訴我。

編輯:看起來我錯過了幾個(我現在添加了)。 實際上http://gcc.gnu.org上的第二頁很好地隱藏了。 常規警告選項C ++選項(向下滾動到警告的底部)

噢,我的所有原始搜索都發布了99%關於如何抑制警告的帖子(非常可怕),但我剛剛遇到這個評論 ,它有一套可愛的標志(一些不太相關):

交叉檢查:

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

所以,我認為這是一個很好的起點。 沒有意識到這是一個騙局,但至少它被埋沒了。 :-)

其中一些已經包含在-Wall-Wextra

C的良好基礎設置是:

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

對於C ++

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

(跳過-Werror for C ++,因為-Weffc++有一些煩惱)

嘗試

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

這是一個快速而骯臟的開始,肯定需要一些調整; 首先,即使您使用適合您的語言的名稱調用編譯器(例如,使用g++ for C ++),您也會收到不適用於該語言的警告(編譯器會拋棄它並拒絕繼續操作,直到你刪除警告)。

另一件事是我添加了-Werror ,因為如果你沒有修復警告,你為什么要關心它們? 您也可以從列表中取出警告。 (例如,我幾乎從不使用-Waggregate-return和C ++。)

如果沒有其他與性能相關的選項( -Wstack-protector ),某些警告將無法執行任何操作。 -fdiagnostics-show-option和GCC手冊是你的朋友。

順便說一句,一些警告是相互排斥的; 特別是使用-Wtraditional-Wold-style-definition沿-Werror ,將無法編譯。

在我的Clion的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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM