Di luar pengaturan -Wall
, dan pengaturan -std=XXX
, apa lagi yang benar-benar berguna, tetapi flag-flag compiler yang kurang dikenal tersedia untuk digunakan di C?
Saya sangat tertarik dengan peringatan tambahan, dan / atau mengubah peringatan menjadi kesalahan dalam beberapa kasus untuk benar-benar meminimalkan ketidakcocokan jenis yang tidak disengaja.
c
gcc
compiler-flags
Matt Joiner
sumber
sumber
-save-temps
,-Wshadow
dan-fmudflap
merupakan penemuan terhebat yang tidak saya ketahui, terima kasih untuk semuanya.gcc -c [flags-go-here] -o myprog.o myprog.c
untuk mengkompilasi (bukan tautan) program C.Jawaban:
Beberapa
-f
opsi pembuatan kode menarik:The
-ftrapv
fungsi akan menyebabkan program untuk membatalkan pada integer ditandatangani overflow (resmi "perilaku undefined" di C).-fverbose-asm
berguna jika Anda mengkompilasi dengan-S
untuk memeriksa hasil perakitan - itu menambahkan beberapa komentar informatif.-finstrument-functions
menambahkan kode untuk memanggil fungsi profil yang disediakan pengguna di setiap entri fungsi dan titik keluar.sumber
-ftrapv
, lihat di sini stackoverflow.com/questions/20851061/… .. sepertinya ada bug yang lama menunggu untuk diperbaiki.Ini milik saya:
-Wextra
,-Wall
: esensial.-Wfloat-equal
: berguna karena biasanya menguji angka floating-point untuk kesetaraan adalah buruk.-Wundef
: memperingatkan jika pengidentifikasi yang tidak diinisialisasi dievaluasi dalam#if
arahan.-Wshadow
: beri peringatan kapan pun variabel lokal memberi bayangan variabel lokal lain, parameter atau variabel global, atau setiap kali fungsi bawaan dibayangi.-Wpointer-arith
: memperingatkan jika ada yang tergantung pada ukuran fungsi atauvoid
.-Wcast-align
: peringatkan setiap kali pointer dilemparkan sedemikian rupa sehingga keselarasan yang diperlukan dari target meningkat Sebagai contoh, ingatkan jika achar *
dilemparkan keint *
mesin di mana bilangan bulat hanya dapat diakses pada batas dua atau empat byte.-Wstrict-prototypes
: memperingatkan jika suatu fungsi dideklarasikan atau didefinisikan tanpa menentukan jenis argumen.-Wstrict-overflow=5
: memperingatkan tentang kasus-kasus di mana kompiler mengoptimalkan berdasarkan asumsi bahwa limpahan yang ditandatangani tidak terjadi. (Nilai 5 mungkin terlalu ketat, lihat halaman manual.)-Wwrite-strings
: berikan string konstantaconst char[
panjang jenis]
sehingga menyalin alamat satu ke non-const char *
pointer akan mendapat peringatan.-Waggregate-return
: memperingatkan jika ada fungsi yang mengembalikan struktur atau serikat didefinisikan atau dipanggil.-Wcast-qual
: peringatkan setiap kali sebuah pointer dilemparkan untuk menghapus kualifikasi tipe dari tipe target * .-Wswitch-default
: peringatkan setiap kaliswitch
pernyataan tidak memilikidefault
kasus * .-Wswitch-enum
: beri peringatan setiap kaliswitch
pernyataan memiliki indeks tipe enumerasi dan tidak memilikicase
untuk satu atau lebih kode nama enumerasi itu * .-Wconversion
: beri peringatan untuk konversi tersirat yang dapat mengubah nilai * .-Wunreachable-code
: peringatkan jika kompiler mendeteksi bahwa kode tidak akan pernah dieksekusi * .Yang ditandai * terkadang memberikan terlalu banyak peringatan palsu, jadi saya menggunakannya sesuai kebutuhan.
sumber
-Wformat=2
: Pemeriksaan format ekstra pada fungsi printf / scanf.-Wall
?-Wwrite-strings
karena saya sangat membencinya.-Wwrite-strings
secara khusus mengatakan itu bukan bagian dari-Wall
: gcc.gnu.org/onlinedocs/gcc/… . Mungkin ada hal lain dalam pengaturan Anda yang mengatur bendera itu? Atau mungkin Anda sedang mengkompilasi C ++?Selalu gunakan
-O
atau di atas (-O1
,-O2
,-Os
, dll). Pada tingkat optimasi default, gcc pergi untuk kecepatan kompilasi dan tidak melakukan analisis yang cukup untuk memperingatkan tentang hal-hal seperti variabel unitial.Pertimbangkan membuat
-Werror
kebijakan, karena peringatan yang tidak menghentikan kompilasi cenderung diabaikan.-Wall
cukup banyak menyalakan peringatan yang sangat mungkin menjadi kesalahan.Peringatan yang termasuk dalam
-Wextra
cenderung menandai kode yang umum dan sah. Mereka mungkin berguna untuk ulasan kode (meskipun program bergaya tidak menemukan banyak jebakan lebih fleksibel), tapi saya tidak akan menyalakannya untuk pengembangan normal.-Wfloat-equal
adalah ide yang baik jika pengembang pada proyek tidak terbiasa dengan floating point, dan ide yang buruk jika ya.-Winit-self
berguna; Saya bertanya-tanya mengapa itu tidak termasuk dalam-Wuninitialized
.-Wpointer-arith
berguna jika Anda memiliki kebanyakan kode portabel yang tidak berfungsi-pedantic
.sumber
Ini meninggalkan hasil preprocessor dan perakitan.
Sumber preprocessed berguna untuk debugging macro.
Perakitan berguna untuk menentukan optimasi apa yang berlaku. Misalnya, Anda mungkin ingin memverifikasi bahwa GCC melakukan optimasi panggilan ekor pada beberapa fungsi rekursif, karena tanpa itu Anda berpotensi meluap tumpukan.
sumber
Saya terkejut belum ada yang mengatakan ini - flag yang paling berguna sejauh yang saya ketahui adalah
-g
yang menempatkan informasi debug ke dalam executable sehingga Anda dapat men-debug dan melangkah melalui sumber (kecuali jika Anda mahir dan membaca perakitan dan sepertistepi
perintah) dari suatu program ketika sedang dieksekusi.sumber
-fmudflap - menambahkan pemeriksaan runtime ke semua operasi pointer berisiko untuk menangkap UB. Ini secara efektif mengimunisasi program Anda lagi buffer overflows dan membantu untuk menangkap semua jenis pointer menggantung.
Ini demo:
sumber
-fmudflap
tidak lagi didukung sejak GCC 4.9, Anda dapatkanwarning: switch '-fmudflap' is no longer supported
. Itu digantikan oleh AddressSanitizer.Tidak benar-benar terkait dengan C / C ++, tetapi bermanfaat:
Letakkan semua flag yang baik di atas (yang telah Anda tentukan) dalam 'file', dan gunakan flag di atas untuk menggunakan semua flag dalam file tersebut.
misalnya:
File: compilerFlags
Kemudian kompilasi:
sumber
-march=native
untuk menghasilkan kode yang dioptimalkan untuk platform (= chip) yang Anda kompilasisumber
Jika Anda perlu mengetahui flag preprocessor yang telah ditentukan oleh kompiler:
sumber
Ini tidak benar-benar membantu untuk mendeteksi kesalahan, tetapi opsi yang jarang disebutkan
-masm=intel
membuat menggunakan-S
untuk memeriksa output perakitan jauh lebih baik.Sintaks perakitan AT&T terlalu menyakitkan bagi saya.
sumber
Makefile saya biasanya berisi
Yang paling penting dari opsi-opsi ini telah dibahas sebelumnya, jadi saya akan menunjukkan dua fitur yang belum ditunjukkan:
Meskipun saya sedang bekerja pada basis kode yang perlu C polos untuk portabilitas ke beberapa platform yang masih tidak memiliki kompiler C ++ yang layak, saya melakukan kompilasi "ekstra" dengan kompiler C ++ (selain kompiler C). Itu memiliki 3 manfaat:
Ya, saya seorang Pollyanna yang sangat optimis yang terus berpikir bahwa pasti setiap bulan sekarang bahwa satu platform akan dinyatakan usang, atau mendapatkan kompiler C ++ yang layak, dan kami akhirnya dapat beralih ke C ++. Dalam pikiran saya, itu tidak bisa dihindari - satu-satunya pertanyaan adalah apakah itu terjadi sebelum atau setelah manajemen akhirnya mengeluarkan semua kuda. :-)
sumber
sumber
-Wold-style-definition
jika Anda harus berurusan dengan residivis yang berpikir fungsi gaya K&R adalah ide yang baik, bahkan dengan deklarasi prototipe. (Saya harus berurusan dengan orang-orang seperti itu. Ini benar-benar mengganggu saya ketika saya menemukan kode baru yang ditulis dalam K&R. Cukup buruk memiliki barang-barang K&R lama yang tidak diperbaiki, tetapi kode baru! Grump !!!)Ini bendera yang bagus yang belum disebutkan:
Berikan kesalahan setiap kali fungsi digunakan sebelum dideklarasikan.
sumber
Manual ini penuh dengan bendera yang menarik dengan deskripsi yang baik. Namun, -Wall mungkin akan membuat gcc setepat mungkin. Jika Anda ingin data yang lebih menarik, Anda harus melihat valgrind atau alat lain untuk memeriksa kesalahan.
sumber
man gcc | nl
melaporkan lebih dari 11000 baris. Itu lebih dari halaman terkenalbash
!Nah,
-Wextra
harus standar juga.-Werror
mengubah peringatan menjadi kesalahan (yang bisa sangat menjengkelkan, terutama jika Anda kompilasi tanpa-Wno-unused-result
).-pedantic
dalam kombinasi denganstd=c89
memberi Anda peringatan tambahan jika Anda menggunakan fitur C99.Tapi itu saja. Anda tidak dapat menyetel kompiler C menjadi sesuatu yang lebih bertipe save daripada C sendiri.
sumber
-M*
keluarga pilihan.Ini memungkinkan Anda menulis membuat file yang secara otomatis mencari tahu file header mana c atau c ++ sumber file Anda. GCC akan menghasilkan file make dengan informasi dependensi ini, dan kemudian Anda menyertakannya dari file make primer Anda.
Berikut adalah contoh makefile yang sangat umum menggunakan -MD dan -MP yang akan mengkompilasi direktori yang penuh dengan c ++ source dan file header, dan mencari tahu semua dependensi secara otomatis:
Berikut adalah posting blog yang membahasnya secara lebih mendalam: http://www.microhowto.info/howto/automatically_generate_makefile_dependencies.html
sumber
Ada
-Werror
, yang memperlakukan semua peringatan sebagai kesalahan dan menghentikan kompilasi. Thegcc
halaman pengguna menjelaskan setiap baris perintah saklar untuk compiler Anda.sumber
gcc
bendera mungkin berbeda antara Anda dan tautan apa pun yang mungkin disarankan siapa pun. Inilah sebabnya mengapa halaman manual disediakan dengan perangkat lunak Anda.-Wfloat-equal
Dari: http://mces.blogspot.com/2005/07/char-const-argv.html
sumber
Saya menemukan utas ini mencari bendera untuk memperbaiki masalah tertentu, saya tidak melihatnya di sini jadi saya akan menambahkannya yang hanya membuat saya bingung pada posting saya :
The
-Wformat=2
flagDan bagian yang sangat penting tentang itu ( menurut manual GCC ):
Jadi, hanya karena Anda memilikinya
-Wall
bukan berarti Anda memiliki semuanya. ;)sumber
Saya terkadang menggunakan
-s
untuk executable yang jauh lebih kecil:Sumber: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
sumber
strip
biner Anda, dengan cara ini Anda dapat memiliki biner dengan informasi debug, hapus nanti untuk distribusi.strip
bekerja juga tetapi-s
bisa lebih cepat dan lebih mudah, meskipun itu tidak rumit seperti berlaristrip
Meskipun jawaban ini mungkin sedikit di luar topik dan pertanyaannya adalah +1 yang berharga dari saya, sejak itu
ada alat yang harus menangkap SEMUA kesalahan dan potensi kesalahan yang mungkin tidak jelas, ada belat yang IMHO melakukan pekerjaan yang lebih baik dalam menangkap kesalahan dibandingkan dengan gcc atau kompiler lain dalam hal ini. Itu adalah alat yang layak untuk dimiliki di dada-alat Anda.Pemeriksaan statis melalui alat jenis serat seperti belat, seharusnya menjadi bagian dari rantai alat penyusun.
sumber
Selain itu
-Wall
, opsi-W
atau-Wextra
(-W
berfungsi dengan versi gcc yang lebih lama dan yang lebih baru; versi yang lebih baru mendukung nama alternatif-Wextra
, yang artinya sama, tetapi lebih deskriptif) memungkinkan berbagai peringatan tambahan.Bahkan ada lebih banyak peringatan yang tidak diaktifkan oleh salah satu dari mereka, umumnya untuk hal-hal yang lebih buruk dipertanyakan. Set pilihan yang tersedia tergantung pada versi gcc yang Anda gunakan - berkonsultasi
man gcc
atauinfo gcc
untuk detail, atau lihat dokumentasi online untuk versi gcc tertentu yang Anda minati. Dan-pedantic
mengeluarkan semua peringatan yang diperlukan oleh standar tertentu yang digunakan (yang tergantung pada opsi lain seperti-std=xxx
atau-ansi
) dan mengeluh tentang penggunaan ekstensi gcc.-Werror
mengubah semua peringatan menjadi kesalahan. Saya tidak berpikir gcc memungkinkan Anda melakukan itu secara selektif untuk peringatan tertentu.Anda mungkin akan menemukan bahwa Anda harus selektif tentang peringatan mana yang diaktifkan berdasarkan per proyek (terutama jika Anda menggunakan
-Werror
), karena file header dari perpustakaan eksternal dapat membuat trip beberapa dari mereka. (-pedantic
khususnya cenderung tidak membantu dalam hal ini, dalam pengalaman saya.)sumber
-Werror=some-warning
.-Wmissing-prototypes
: Jika fungsi global didefinisikan tanpa deklarasi prototipe sebelumnya.-Wformat-security
: Memperingatkan penggunaan fungsi format yang mewakili kemungkinan masalah keamanan. Saat ini, ini memperingatkan tentang panggilan keprintf
danscanf
fungsi di mana string format bukan string literal dan tidak ada argumen formatsumber
-Werror=return-type
: Menerapkan kesalahan saat fungsi tidak kembali di gcc. Itu/we4716
di Visual Studio.-Werror=implicit-function-declaration
: Menerapkan kesalahan saat fungsi digunakan tanpa didefinisikan / tidak disertakan. Itu/we4013
di Visual Studio.-Werror=incompatible-pointer-types
: Selesaikan kesalahan saat tipe pointer tidak cocok dengan tipe pointer yang diharapkan. Itu/we4133
di Visual Studio.Sebenarnya, saya ingin menyimpan kode-C lintas-platform, dan saya menggunakan CMake, dan saya memasukkan cflag yang disediakan ke dalam CMakeLists.txt seperti:
sumber