Tanda untuk mengaktifkan peringatan g ++ yang menyeluruh dan panjang

122

Seringkali di C di bawah gcc, saya akan mulai dengan serangkaian tanda peringatan berikut (dirakit dengan menyakitkan dari berbagai sumber):

-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

Saya akan membangun (setidaknya versi debug saya) dengan rangkaian peringatan ini dan memperbaiki semua yang saya bisa (biasanya semuanya), dan kemudian hanya menghapus tanda jika tidak relevan atau tidak dapat diperbaiki (hampir tidak pernah terjadi). Kadang-kadang, saya juga akan menambahkan -Werrorjika saya harus menjauh saat menyusun.

Saya baru saja mengambil C ++ (ya, saya 15 tahun ketinggalan zaman), dan saya ingin memulai dengan langkah yang benar.

Pertanyaan saya adalah: Apakah seseorang memiliki kumpulan peringatan lengkap serupa yang telah dikompilasi sebelumnya untuk C ++ di bawah g++? (Saya tahu banyak dari mereka akan sama.)

Sdaz MacSkibbons
sumber
69
Apa kebutuhan gcc (karena itu memutuskan untuk terang-terangan berbohong tentang -Wall) adalah -Wbloody_everythingbendera :-)
paxdiablo
Anda dapat menandai pertanyaan Anda sebagai penipuan, tetapi Anda juga dapat menempatkan hasil edit terakhir Anda sebagai jawaban karena Anda benar-benar menjawab pertanyaan Anda. Dan saya akan senang untuk memberi
suara positif
4
OP dan @paxdiablo: GCC secara konsisten menolak hal semacam ini, tetapi tersedia di Clang via -Weverything. Saya telah membaca bahwa bahkan pengembang Clang ++ sedikit khawatir tentang pengguna yang mengaktifkannya; rupanya itu dimaksudkan untuk penggunaan pengembangan internal saja. Ini tidak masuk akal, karena menyalakan -Weverythingmungkin adalah cara terbaik untuk menemukan peringatan yang berpotensi membantu yang tidak Anda ketahui sebelumnya.
Kyle Strand
1
OP dan @paxdiablo Sekarang ada cara untuk mengetahui daftar lengkap peringatan untuk versi GCC yang diberikan: github.com/barro/compiler-warnings
Kyle Strand
1
Kemungkinan duplikat dari Bagaimana cara mengaktifkan (secara harfiah) SEMUA peringatan GCC?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Jawaban:

138

Saya memeriksa dan menemukan set minimal yang harus mendapatkan tingkat peringatan maksimum. Saya kemudian menghapus dari daftar itu serangkaian peringatan yang saya rasa tidak benar-benar menunjukkan sesuatu yang buruk sedang terjadi, atau memiliki terlalu banyak positif palsu untuk digunakan dalam membangun nyata. Saya berkomentar mengapa masing-masing yang saya kecualikan dikecualikan. Ini adalah rangkaian peringatan terakhir yang saya sarankan:

-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

Peringatan dipertanyakan yang ada:

  • Saya menyertakan -Wno-unusedkarena saya sering memiliki variabel yang saya tahu akan saya gunakan nanti, tetapi belum memiliki fungsionalitas yang ditulis untuk. Menghapus peringatan tentang itu memungkinkan saya untuk menulis dalam gaya yang saya sukai sesekali menunda implementasi sesuatu. Berguna untuk mematikannya sesekali untuk memastikan tidak ada yang lolos dari celah.

  • -Wdisabled-optimizationsepertinya pengaturan preferensi pengguna yang kuat. Saya baru saja menambahkan yang ini ke build saya (hanya untuk build yang dioptimalkan untuk alasan yang jelas) dan tidak menghasilkan apa-apa, jadi sepertinya bukan peringatan yang cerewet, setidaknya untuk cara saya membuat kode. Saya memasukkannya (meskipun kode yang memicu peringatan ini tidak selalu salah) karena saya percaya dalam bekerja dengan alat saya alih-alih melawannya. Jika gcc memberi tahu saya bahwa ia tidak dapat mengoptimalkan kode untuk cara saya menulisnya, maka saya harus melihat untuk menulis ulang. Saya curiga bahwa kode yang memicu peringatan ini dapat mengambil manfaat dari menjadi lebih modular, terlepas dari itu, jadi meskipun kode tersebut secara teknis tidak salah (mungkin), secara gaya memang demikian.

  • -Wfloat-equalmemperingatkan untuk perbandingan kesetaraan yang aman (khususnya, perbandingan dengan nilai yang tidak dihitung -1). Contoh dalam kode saya di mana saya menggunakan ini adalah bahwa saya memiliki vektor float. Saya membahas vektor ini, dan ada beberapa elemen yang belum dapat saya evaluasi apa yang seharusnya, jadi saya menetapkannya ke -1.0f (karena masalah saya hanya menggunakan bilangan positif, -1 di luar domain). Saya kemudian pergi melalui dan memperbarui nilai -1.0f. Itu tidak dengan mudah meminjamkan dirinya ke metode operasi yang berbeda. Saya menduga bahwa kebanyakan orang tidak memiliki masalah ini, dan perbandingan angka pasti dalam floating point mungkin merupakan kesalahan, jadi saya memasukkannya ke dalam daftar default.

  • -Wold-style-castmemiliki banyak positif palsu dalam kode perpustakaan yang saya gunakan. Secara khusus, keluarga fungsi htonl yang digunakan dalam jaringan, serta implementasi enkripsi Rijndael (AES) yang saya gunakan memiliki cast gaya lama yang mengingatkan saya. Saya bermaksud untuk mengganti keduanya, tetapi saya tidak yakin apakah ada hal lain dalam kode saya yang akan dikeluhkan. Sebagian besar pengguna mungkin harus mengaktifkan ini secara default.

  • -Wsign-conversionadalah yang sulit (dan hampir tidak masuk daftar). Mengaktifkannya di kode saya menghasilkan sejumlah besar peringatan (100+). Hampir semuanya tidak bersalah. Namun, saya telah berhati-hati untuk menggunakan bilangan bulat yang ditandatangani di mana pun saya tidak yakin, meskipun untuk domain masalah khusus saya, saya biasanya akan mendapatkan sedikit peningkatan efisiensi menggunakan nilai yang tidak ditandatangani karena banyaknya pembagian bilangan bulat yang saya lakukan. Saya mengorbankan efisiensi ini karena saya khawatir tentang secara tidak sengaja mempromosikan bilangan bulat bertanda ke unsigned dan kemudian membagi (yang tidak aman, tidak seperti penambahan, pengurangan, dan perkalian). Mengaktifkan peringatan ini memungkinkan saya mengubah sebagian besar variabel saya dengan aman ke tipe unsigned dan menambahkan beberapa cast di beberapa tempat lain. Saat ini agak sulit digunakan karena peringatannya tidak terlalu pintar. Misalnya, jika Anda melakukannyaunsigned short + (integral constant expression), hasil tersebut secara implisit dipromosikan menjadi int. Kemudian memperingatkan tentang potensi masalah tanda jika Anda menetapkan nilai itu ke unsignedatau unsigned short, meskipun aman. Ini jelas merupakan peringatan paling opsional untuk hampir semua pengguna.

  • -Wsign-promo: lihat -Wsign-conversion.

  • -Wswitch-defaulttampaknya tidak berguna (Anda tidak selalu menginginkan kasus default jika Anda telah menyebutkan semua kemungkinan secara eksplisit). Namun, mengaktifkan peringatan ini dapat memberlakukan sesuatu yang mungkin merupakan ide bagus. Untuk kasus di mana Anda secara eksplisit ingin mengabaikan semuanya kecuali kemungkinan yang terdaftar (tetapi nomor lain dimungkinkan), masukkandefault: break;untuk membuatnya eksplisit. Jika Anda secara eksplisit menghitung semua kemungkinan, mengaktifkan peringatan ini akan membantu memastikan bahwa Anda memasukkan sesuatu seperti assert (false) untuk memastikan bahwa Anda telah benar-benar mencakup semua opsi yang memungkinkan. Ini memungkinkan Anda untuk secara eksplisit tentang apa domain masalah Anda dan secara terprogram menerapkannya. Namun, Anda harus berhati-hati dalam hanya menempelkan assert (false) di mana-mana. Ini lebih baik daripada tidak melakukan apa pun dengan kasus default, tetapi seperti biasa dengan assert, ini tidak akan berfungsi dalam versi rilis. Dengan kata lain, Anda tidak dapat mengandalkannya untuk memvalidasi nomor yang Anda peroleh dari, katakanlah, koneksi jaringan atau database yang tidak dapat Anda kendalikan secara mutlak. Pengecualian atau pengembalian lebih awal adalah cara terbaik untuk menanganinya (tetapi tetap mengharuskan Anda memiliki kasus default!).

  • -Werroradalah yang penting bagi saya. Saat mengompilasi kode dalam jumlah besar dalam build multi-thread dengan beberapa target, peringatan akan mudah lewat. Mengubah peringatan menjadi kesalahan memastikan bahwa saya menyadarinya.

Kemudian ada satu set peringatan yang tidak termasuk dalam daftar di atas karena menurut saya tidak berguna. Ini adalah peringatan dan komentar saya tentang mengapa saya tidak memasukkannya ke dalam daftar default:

Peringatan yang tidak ada:

  • -Wabitidak diperlukan karena saya tidak menggabungkan binari dari kompiler yang berbeda. Saya tetap mencoba mengompilasinya, dan tidak memicu, jadi sepertinya tidak bertele-tele.

  • -Waggregate-returnbukanlah sesuatu yang saya anggap sebagai kesalahan. Misalnya, ini dipicu saat menggunakan for loop berbasis rentang pada vektor kelas. Pengoptimalan nilai kembali harus menangani semua efek negatif dari ini.

  • -Wconversiondipicu pada kode ini: short n = 0; n += 2;Konversi implisit ke int menyebabkan peringatan saat dikonversi kembali ke jenis targetnya.

  • -Weffc++termasuk peringatan jika semua anggota data tidak diinisialisasi dalam daftar penginisialisasi. Saya sengaja tidak melakukan ini dalam banyak kasus, jadi rangkaian peringatan terlalu berantakan untuk bisa digunakan. Akan sangat membantu untuk mengaktifkannya sesekali dan memindai peringatan lain (seperti destruktor non-virtual dari kelas dasar). Ini akan lebih berguna sebagai kumpulan peringatan (seperti -Wall) daripada satu peringatan saja.

  • -Winlinetidak ada karena saya tidak menggunakan kata kunci inline untuk tujuan pengoptimalan, hanya untuk mendefinisikan fungsi inline di header. Saya tidak peduli jika pengoptimal benar-benar menyejajarkannya. Peringatan ini juga mengeluh jika tidak bisa sebaris fungsi yang dideklarasikan dalam badan kelas (seperti penghancur virtual kosong).

  • -Winvalid-pch hilang karena saya tidak menggunakan header yang telah dikompilasi sebelumnya.

  • -Wmissing-format-attributetidak digunakan karena saya tidak menggunakan ekstensi gnu. Sama untuk -Wsuggest-attributedan beberapa lainnya

  • Berpotensi terkenal karena ketidakhadirannya -Wno-long-long, yang tidak saya butuhkan. Saya mengkompilasi dengan -std=c++0x( -std=c++11di GCC 4.7), yang menyertakan long longtipe integer. Mereka yang terjebak kembali pada C ++ 98 / C ++ 03 dapat mempertimbangkan untuk menambahkan pengecualian itu dari daftar peringatan.

  • -Wnormalized=nfc sudah menjadi opsi default, dan tampaknya yang terbaik.

  • -Wpaddeddiaktifkan sesekali untuk mengoptimalkan tata letak kelas, tetapi tidak dibiarkan karena tidak semua kelas memiliki cukup elemen untuk menghapus bantalan di bagian akhir. Secara teori saya bisa mendapatkan beberapa variabel tambahan secara 'gratis', tetapi itu tidak sebanding dengan upaya ekstra untuk mempertahankannya (jika ukuran kelas saya berubah, tidak mudah untuk menghapus variabel bebas yang sebelumnya).

  • -Wstack-protector tidak digunakan karena saya tidak menggunakan -fstack-protector

  • -Wstrict-aliasing=3diaktifkan oleh -Walldan merupakan yang paling akurat, tetapi sepertinya level 1 dan 2 memberikan lebih banyak peringatan. Secara teori, level yang lebih rendah adalah peringatan yang 'lebih kuat', tetapi mengorbankan lebih banyak positif palsu. Kode pengujian saya sendiri terkompilasi dengan rapi di bawah semua 3 level.

  • -Wswitch-enumbukanlah perilaku yang saya inginkan. Saya tidak ingin menangani setiap pernyataan switch secara eksplisit. Akan berguna jika bahasa memiliki beberapa mekanisme untuk mengaktifkan ini pada pernyataan sakelar yang ditentukan (untuk memastikan bahwa perubahan masa depan pada enum ditangani di mana pun mereka perlu), tetapi itu berlebihan untuk pengaturan "semua atau tidak sama sekali".

  • -Wunsafe-loop-optimizationsmenyebabkan terlalu banyak peringatan palsu. Mungkin berguna untuk menerapkan yang satu ini secara berkala dan memverifikasi hasilnya secara manual. Sebagai contoh, ini menghasilkan peringatan ini dalam kode saya ketika saya mengulang semua elemen dalam vektor untuk menerapkan satu set fungsi ke mereka (menggunakan for loop berbasis rentang). Ini juga merupakan peringatan untuk konstruktor dari array const dari const std :: string (di mana ini bukan loop dalam kode pengguna).

  • -Wzero-as-null-pointer-constantdan -Wuseless-castmerupakan peringatan khusus GCC 4.7, yang akan saya tambahkan saat saya bertransisi ke GCC 4.7.

Saya telah mengajukan beberapa laporan bug / permintaan peningkatan di gcc sebagai hasil dari beberapa penelitian ini, jadi semoga pada akhirnya saya dapat menambahkan lebih banyak peringatan dari daftar "jangan sertakan" ke daftar "sertakan" . Daftar ini mencakup semua peringatan yang disebutkan di utas ini (ditambah saya pikir beberapa tambahan). Banyak dari peringatan yang tidak disebutkan secara eksplisit dalam posting ini dimasukkan sebagai bagian dari peringatan lain yang saya sebutkan. Jika ada yang memperhatikan peringatan apa pun yang dikecualikan dari posting ini sepenuhnya, beri tahu saya.

edit: Sepertinya saya telah melewatkan beberapa (yang sekarang telah saya tambahkan). Sebenarnya ada halaman kedua di http://gcc.gnu.org yang cukup tersembunyi. Opsi peringatan umum dan opsi C ++ (gulir ke bawah ke bawah untuk peringatan)

David Stone
sumber
Saya baru-baru ini mengirimkan permintaan peningkatan berdasarkan penelitian saya untuk jawaban ini: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Ini akan secara dramatis menyederhanakan situasi peringatan dengan membuat tingkat peringatan. Dalam proposal saya, rangkaian peringatan yang saya sarankan kira-kira -W4, dengan proposal tambahan untuk membuat -Winf, yang berarti -Berat-dan-Saya-sungguh-sungguh-sungguh-kali ini
David Stone
Permintaan peningkatan yang akan menyebabkan bagian dari -Wpadded ditambahkan ke daftar yang direkomendasikan: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone
Permintaan peningkatan yang akan menyebabkan bagian dari -Weffc ++ ditambahkan ke daftar yang direkomendasikan: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone
1
@Predelnik: Ini lebih rumit dari itu. -Wswitch-enummemperingatkan jika Anda tidak secara eksplisit menangani setiap nilai enumerasi dalam sebuah sakelar, dan defaulttidak dihitung sebagai eksplisit. Di sisi lain, -Wswitch-defaultmemperingatkan Anda jika sakelar Anda tidak memiliki defaultcasing, meskipun Anda telah secara eksplisit mencakup semua kemungkinan nilai.
David Stone
2
BTW - gunakan -isystemalih-alih -Ipada "kode perpustakaan lama" Anda untuk mencegah semua positif palsu itu
galois
39

Duh, semua pencarian asli saya menghasilkan 99% posting tentang cara menekan peringatan (cukup menakutkan), tetapi saya baru saja menemukan komentar ini , yang memiliki kumpulan bendera yang indah ini (beberapa kurang relevan):

Periksa silang dengan:

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

Jadi, saya pikir itu titik awal yang bagus. Tidak menyadari ini adalah penipuan, tapi setidaknya itu terkubur dalam-dalam. :-)

Sdaz MacSkibbons
sumber
1
Mungkin, tapi itu tampaknya berubah di antara versi, dan mungkin karena bintik matahari dan RMS, jadi terlalu eksplisit mungkin tidak ada salahnya. Ini adalah titik awal yang bagus.
Sdaz MacSkibbons
3
Dari grep cepat 4.5.2 c-opts.c / opts.c untuk 'case OPT_W', Anda hilang: luapan ketat, undef, sentinel nul ketat, dinormalisasi, multichar, deklarasi fungsi implisit, usang, label endif, komentar s , makro bawaan yang didefinisikan ulang, lebih besar dari, lebih besar dari persamaan, abi. Sungguh gila bahwa tidak ada opsi baris perintah untuk mencantumkannya.
Tony Delroy
3
Saya pikir itu lebih gila yang -Walltidak melakukan apa yang diharapkan. Tapi terima kasih, beberapa di antaranya terlihat sangat berguna!
Sdaz MacSkibbons
1
Peringatan penonaktifan ada tempatnya. Bagaimanapun, itu adalah "peringatan". Situasi lain adalah ketika Anda mengaktifkan bendera yang memungkinkan beberapa peringatan, tetapi Anda ingin selektif tentangnya.
Tamás Szelei
1
Bagaimana Anda bisa menggunakannya -Waggregate-return? Ini memberi saya peringatan untuk setiap penggunaanbegin/end()
Flamefire
13

Beberapa di antaranya sudah termasuk dalam -Wallatau -Wextra.

Pengaturan dasar yang baik untuk C adalah:

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

dan untuk C ++

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

(melewatkan -WerrorC ++ karena -Weffc++memiliki beberapa gangguan)

Šimon Tóth
sumber
10
-Werror dapat dinonaktifkan untuk jenis peringatan tertentu, misalnya: -Werror -Weffc ++ -Wno-error = effc ++
Robert Hensing
2
ansi : Dalam mode C, ini sama dengan -std=c89. Dalam mode C ++, ini setara dengan -std=c++98. yaitu jika Anda menentukan yang lain std, jangan gunakanansi
Sean Breckenridge
2

Mencoba

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

Itu awal yang cepat dan kotor yang pasti membutuhkan beberapa penyetelan; untuk satu hal, bahkan jika Anda memanggil kompilator dengan nama yang sesuai untuk bahasa Anda (misalnya g++untuk C ++), Anda akan mendapatkan peringatan yang tidak berlaku untuk bahasa itu (dan kompilator akan angkat tangan dan menolak untuk melanjutkan sampai Anda hapus peringatan).

Hal lain adalah saya menambahkan -Werror, karena jika Anda tidak memperbaiki peringatan, mengapa Anda peduli untuk menyalakannya? Anda juga dapat mengeluarkan peringatan dari daftar. (Misalnya, saya hampir tidak pernah menggunakan -Waggregate-returnC ++.)

Beberapa peringatan tidak akan melakukan apa pun tanpa opsi terkait kinerja lainnya ( -Wstack-protector). -fdiagnostics-show-optiondan manual GCC adalah teman Anda.

Ngomong-ngomong, beberapa peringatan bersifat eksklusif; secara khusus menggunakan -Wtraditionaldan -Wold-style-definitionbersama -Werror, tidak akan dikompilasi.

Nathan Paul Simons
sumber
0

Di CmakeLists.txt Clion saya

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)
snr
sumber