Mengapa mengaktifkan peringatan?
Kompiler C dan C ++ terkenal buruk dalam melaporkan beberapa kesalahan umum programmer secara default , seperti:
- lupa menginisialisasi variabel
- lupa
return
nilai dari suatu fungsi
- argumen di
printf
dan scanf
keluarga tidak cocok dengan string format
- suatu fungsi digunakan tanpa dideklarasikan sebelumnya (hanya C)
Ini dapat dideteksi dan dilaporkan, biasanya tidak secara default; fitur ini harus secara eksplisit diminta melalui opsi kompiler.
Bagaimana cara mengaktifkan peringatan?
Ini tergantung pada kompiler Anda.
Microsoft C dan C ++ compiler memahami switch seperti /W1
, /W2
, /W3
, /W4
dan /Wall
. Gunakan setidaknya /W3
. /W4
dan /Wall
mungkin memancarkan peringatan palsu untuk file header sistem, tetapi jika proyek Anda dikompilasi dengan bersih dengan salah satu opsi ini, lakukan. Opsi-opsi ini saling eksklusif.
Kebanyakan kompiler lain memahami opsi seperti -Wall
, -Wpedantic
dan -Wextra
. -Wall
sangat penting dan sisanya direkomendasikan (perhatikan bahwa, terlepas dari namanya, -Wall
hanya memungkinkan peringatan yang paling penting, tidak semuanya ). Opsi-opsi ini dapat digunakan secara terpisah atau bersama-sama.
IDE Anda mungkin memiliki cara untuk mengaktifkannya dari antarmuka pengguna.
Mengapa memperlakukan peringatan sebagai kesalahan? Itu hanya peringatan!
Peringatan kompiler menandakan masalah yang berpotensi serius dalam kode Anda. Masalah-masalah yang tercantum di atas hampir selalu berakibat fatal; orang lain mungkin atau mungkin tidak, tetapi Anda ingin kompilasi gagal meskipun ternyata alarm palsu. Selidiki setiap peringatan, temukan akar masalahnya, dan perbaiki. Jika alarm palsu, atasi - yaitu, gunakan fitur atau konstruksi bahasa yang berbeda sehingga peringatan tidak lagi terpicu. Jika ini terbukti sangat sulit, nonaktifkan peringatan tersebut berdasarkan kasus per kasus.
Anda tidak ingin hanya meninggalkan peringatan sebagai peringatan meskipun semua itu adalah alarm palsu. Bisa saja OK untuk proyek yang sangat kecil di mana jumlah total peringatan yang dikeluarkan kurang dari 7. Ada yang lebih, dan mudah untuk peringatan baru hilang dalam banjir yang sudah dikenal lama. Jangan biarkan itu terjadi. Hanya menyebabkan semua proyek Anda dikompilasi dengan bersih.
Catatan ini berlaku untuk pengembangan program. Jika Anda merilis proyek Anda ke dunia dalam bentuk sumber, maka mungkin ide yang baik untuk tidak memasok -Werror
atau setara dalam skrip build yang dirilis . Orang-orang mungkin mencoba membangun proyek Anda dengan versi kompiler yang berbeda, atau dengan kompiler yang berbeda secara bersamaan, yang mungkin memiliki serangkaian peringatan yang berbeda yang diaktifkan. Anda mungkin ingin bangunan mereka berhasil. Itu masih merupakan ide yang baik untuk tetap mengaktifkan peringatan, sehingga orang yang melihat pesan peringatan dapat mengirimkan laporan bug atau patch kepada Anda.
Bagaimana memperlakukan peringatan sebagai kesalahan?
Sekali lagi ini dilakukan dengan sakelar kompiler. /WX
untuk Microsoft, kebanyakan digunakan orang lain -Werror
. Dalam kedua kasus tersebut, kompilasi akan gagal jika ada peringatan yang dihasilkan.
C, yang terkenal, adalah bahasa tingkat rendah seperti HLL. C ++, meskipun sepertinya bahasa tingkat jauh lebih tinggi dari C, masih memiliki beberapa sifat. Dan salah satu dari sifat-sifat itu adalah bahwa bahasa dirancang oleh programmer, untuk programmer - dan, khususnya, programmer yang tahu apa yang mereka lakukan.
[Untuk sisa jawaban ini saya akan fokus pada C. Sebagian besar dari apa yang akan saya katakan juga berlaku untuk C ++, meskipun mungkin tidak sekuat itu. Meskipun seperti yang dikatakan Bjarne Stroustrup dengan terkenal, "C membuatnya mudah untuk menembak diri sendiri di kaki; C ++ membuatnya lebih sulit, tetapi ketika Anda melakukannya, itu akan menghancurkan seluruh kaki Anda." ]
Jika Anda tahu apa yang Anda lakukan - benar - benar tahu apa yang Anda lakukan - kadang-kadang Anda mungkin harus "melanggar aturan". Tapi sebagian besar waktu, sebagian besar dari kita akan setuju bahwa aturan yang bermaksud baik membuat kita semua dari masalah, dan yang melanggar aturan itu sepanjang waktu adalah ide yang buruk.
Tetapi dalam C dan C ++, ada sejumlah besar hal yang dapat Anda lakukan yang merupakan "ide buruk" tetapi tidak secara formal "melanggar aturan". Kadang-kadang mereka adalah ide yang buruk beberapa waktu (tetapi mungkin bisa dipertahankan kali lain); terkadang mereka adalah ide yang buruk hampir sepanjang waktu. Tetapi tradisi selalu tidak memperingatkan tentang hal-hal ini - karena, sekali lagi, asumsi adalah bahwa programmer tahu apa yang mereka lakukan, mereka tidak akan melakukan hal-hal ini tanpa alasan yang baik, mereka akan terganggu oleh banyak peringatan yang tidak perlu.
Tetapi tentu saja tidak semua programmer benar - benar tahu apa yang mereka lakukan. Dan, khususnya, setiap programmer C (tidak peduli seberapa berpengalaman) melewati fase menjadi programmer C awal. Dan bahkan pemrogram C yang berpengalaman bisa ceroboh dan membuat kesalahan.
Akhirnya, pengalaman tidak hanya menunjukkan bahwa pemrogram melakukan kesalahan, tetapi bahwa kesalahan ini dapat memiliki konsekuensi nyata dan serius. Jika Anda membuat kesalahan, dan kompiler tidak memperingatkan Anda tentang hal itu, dan entah bagaimana program tidak segera crash atau melakukan sesuatu yang jelas salah karena kesalahan itu, kesalahan tersebut dapat bersembunyi di sana, disembunyikan, kadang-kadang selama bertahun-tahun, hingga menyebabkan masalah yang sangat besar.
Jadi ternyata, pada umumnya, peringatan adalah ide yang bagus. Bahkan pemrogram berpengalaman telah belajar (sebenarnya, " terutama pemrogram berpengalaman telah belajar") bahwa, secara seimbang, peringatan cenderung lebih baik daripada merugikan. Untuk setiap kali Anda melakukan kesalahan dengan sengaja dan peringatan itu mengganggu, mungkin ada setidaknya sepuluh kali Anda melakukan kesalahan karena kecelakaan dan peringatan itu menyelamatkan Anda dari masalah lebih lanjut. Dan sebagian besar peringatan dapat dinonaktifkan atau dikerjakan untuk beberapa saat ketika Anda benar-benar ingin melakukan hal yang "salah".
(Sebuah contoh klasik dari suatu "kesalahan" adalah tes
if(a = b)
Sebagian besar waktu, ini adalah kesalahan, sehingga sebagian besar kompiler hari ini memperingatkan tentang hal itu -.. Beberapa bahkan secara default Tetapi jika Anda benar-benar ingin baik assignb
kea
dan uji hasilnya, Anda dapat menonaktifkan peringatan dengan mengetikif((a = b))
.)Pertanyaan kedua adalah, mengapa Anda ingin meminta kompiler untuk memperlakukan peringatan sebagai kesalahan? Saya akan mengatakan itu karena sifat manusia, khususnya, reaksi yang terlalu mudah untuk mengatakan "Oh, itu hanya peringatan, itu tidak begitu penting, saya akan membersihkannya nanti." Tetapi jika Anda suka menunda-nunda (dan saya tidak tahu tentang Anda, tapi saya suka menunda - nunda) mudah untuk menunda pembersihan pada dasarnya - dan jika Anda terbiasa mengabaikan peringatan, itu semakin mudah dan lebih mudah untuk melewatkan pesan peringatan penting yang ada di sana, tanpa disadari, di tengah semua yang Anda abaikan.
Jadi meminta kompiler untuk memperlakukan peringatan karena kesalahan adalah trik kecil yang bisa Anda mainkan sendiri untuk mengatasi kelemahan manusia ini.
Secara pribadi, saya tidak berkeras memperlakukan peringatan sebagai kesalahan. (Sebenarnya, jika saya jujur, saya dapat mengatakan bahwa saya hampir tidak pernah mengaktifkan opsi itu dalam pemrograman "pribadi" saya.) Tetapi Anda dapat yakin bahwa saya mengaktifkan opsi itu di tempat kerja, di mana panduan gaya kami (yang saya panduankan) menulis) mengamanatkan penggunaannya. Dan saya akan mengatakan - saya menduga sebagian besar programmer profesional akan mengatakan - bahwa setiap toko yang tidak memperlakukan peringatan karena kesalahan dalam C berperilaku tidak bertanggung jawab, tidak mematuhi praktik terbaik industri yang diterima secara umum.
sumber
if(a = b)
, oleh karena itu kita tidak perlu memperingatkan tentang hal itu." (Kemudian seseorang menghasilkan daftar 10 bug kritis dalam 10 produk yang dirilis yang dihasilkan dari kesalahan khusus ini.) "Oke, tidak ada programmer C yang berpengalaman yang akan pernah menulis itu ..."if (returnCodeFromFoo = foo(bar))
dan bersungguh-sungguh, untuk menangkap dan menguji kode di satu tempat (Asumsikan satu - satunya tujuanfoo
adalah untuk memiliki efek samping!) Fakta bahwa seorang programmer yang benar-benar berpengalaman mungkin tahu ini bukan gaya pengkodean yang bagus adalah intinya;)if (returnCodeFromFoo = foo(bar))
, maka mereka memberikan komentar dan mematikan peringatan (sehingga ketika programmer pemeliharaan melihatnya 4 tahun kemudian, dia akan menyadari bahwa kode itu disengaja. Karena itu, saya bekerja dengan seseorang yang (dalam Microsoft C ++ land) bersikeras bahwa menggabungkan / Tembok dengan memperlakukan peringatan sebagai kesalahan adalah cara untuk pergi. Eh, itu tidak (kecuali jika Anda ingin memasukkan banyak komentar penindasan)Peringatan terdiri dari saran terbaik yang bisa dibuat oleh beberapa pengembang C ++ paling terampil dalam sebuah aplikasi. Mereka layak dijaga.
C ++, sebagai bahasa lengkap Turing, memiliki banyak kasus di mana kompiler hanya harus percaya bahwa Anda tahu apa yang Anda lakukan. Namun, ada banyak kasus di mana kompiler dapat menyadari bahwa Anda mungkin tidak bermaksud untuk menulis apa yang Anda tulis. Contoh klasik adalah kode printf () yang tidak cocok dengan argumen, atau std :: strings dilewatkan ke printf (bukan yang pernah terjadi pada saya!). Dalam kasus ini, kode yang Anda tulis bukan kesalahan. Ini adalah ekspresi C ++ yang valid dengan interpretasi yang valid untuk ditindaklanjuti oleh kompiler. Tetapi kompiler memiliki firasat yang kuat bahwa Anda hanya mengabaikan sesuatu yang mudah dideteksi oleh kompiler modern. Ini adalah peringatan. Mereka adalah hal-hal yang jelas bagi kompiler, menggunakan semua aturan ketat C ++ yang dapat digunakannya, yang mungkin Anda abaikan.
Menonaktifkan peringatan, atau mengabaikannya, seperti memilih untuk mengabaikan saran gratis dari mereka yang lebih terampil daripada Anda. Ini adalah pelajaran dalam huberis yang berakhir ketika Anda terbang terlalu dekat dengan matahari dan sayap Anda meleleh, atau kesalahan memori kerusakan terjadi. Di antara keduanya, aku akan jatuh dari langit kapan saja!
"Perlakukan peringatan sebagai kesalahan" adalah versi ekstrem dari filosofi ini. Idenya di sini adalah bahwa Anda menyelesaikan setiap peringatan yang diberikan kompiler kepada Anda - Anda mendengarkan setiap nasihat gratis dan menindaklanjutinya. Apakah ini model yang baik untuk pengembangan untuk Anda tergantung pada tim dan produk apa yang sedang Anda kerjakan. Ini adalah pendekatan pertapaan yang mungkin dimiliki seorang bhikkhu. Bagi sebagian orang, ini bekerja dengan baik. Bagi yang lain, tidak.
Pada banyak aplikasi saya, kami tidak memperlakukan peringatan sebagai kesalahan. Kami melakukan ini karena aplikasi khusus ini perlu dikompilasi pada beberapa platform dengan beberapa kompiler dari berbagai usia. Terkadang kami menemukan bahwa sebenarnya tidak mungkin untuk memperbaiki peringatan di satu sisi tanpa mengubahnya menjadi peringatan di platform lain. Jadi kami hanya berhati-hati. Kami menghormati peringatan, tetapi kami tidak membungkuk untuk itu.
sumber
equals
/hashCode
), dan ini adalah kualitas masalah implementasi yang dilaporkan.Tidak hanya menangani peringatan membuat kode lebih baik, itu membuat Anda seorang programmer yang lebih baik. Peringatan akan memberi tahu Anda tentang hal-hal yang mungkin tampak sedikit bagi Anda hari ini, tetapi suatu hari kebiasaan buruk itu akan kembali dan menggigit kepalamu.
Gunakan tipe yang benar, kembalikan nilai itu, evaluasi kembali nilai itu. Luangkan waktu dan renungkan "Apakah ini benar-benar tipe yang tepat dalam konteks ini?" "Apakah saya perlu mengembalikan ini?" Dan masalah besar; "Apakah kode ini akan portabel untuk 10 tahun ke depan?"
Biasakan menulis kode bebas peringatan di tempat pertama.
sumber
Jawaban lainnya sangat bagus dan saya tidak ingin mengulangi apa yang mereka katakan.
Satu aspek lain untuk "mengapa mengaktifkan peringatan" yang belum disentuh dengan benar adalah bahwa mereka sangat membantu dalam pemeliharaan kode. Ketika Anda menulis sebuah program dengan ukuran yang signifikan, menjadi tidak mungkin untuk menyimpan semuanya di kepala Anda sekaligus. Anda biasanya memiliki satu atau tiga fungsi yang secara aktif Anda tulis dan pikirkan, dan mungkin satu atau tiga file di layar yang dapat Anda rujuk, tetapi sebagian besar program ada di latar belakang di suatu tempat dan Anda harus percaya bahwa itu terus bekerja.
Memiliki peringatan, dan membuatnya seenergi dan di wajah Anda mungkin, membantu mengingatkan Anda jika sesuatu yang Anda ubah membuat masalah untuk sesuatu yang tidak dapat Anda lihat.
Ambil contoh, peringatan dentang
-Wswitch-enum
. Itu memicu peringatan jika Anda menggunakan sakelar pada enum dan melewatkan salah satu nilai enum yang mungkin. Ini adalah sesuatu yang Anda mungkin berpikir untuk membuat kesalahan: Anda mungkin setidaknya melihat daftar nilai enum ketika Anda menulis pernyataan switch. Anda bahkan mungkin memiliki IDE yang menghasilkan opsi sakelar untuk Anda, tanpa meninggalkan ruang untuk kesalahan manusia.Peringatan ini benar-benar muncul ketika, enam bulan kemudian Anda menambahkan entri lain yang mungkin ke enum. Sekali lagi, jika Anda berpikir tentang kode yang dimaksud, Anda mungkin akan baik-baik saja. Tetapi jika enum ini digunakan untuk berbagai tujuan yang berbeda dan ini untuk salah satu yang Anda butuhkan opsi tambahan, sangat mudah untuk lupa memperbarui sakelar dalam file yang belum Anda sentuh selama 6 bulan.
Anda dapat memikirkan peringatan dengan cara yang sama seperti yang Anda pikirkan tentang kasus uji otomatis: mereka membantu Anda memastikan bahwa kode masuk akal dan melakukan apa yang Anda butuhkan saat pertama kali menulisnya, tetapi mereka membantu lebih banyak lagi untuk memastikannya terus melakukan apa yang Anda butuhkan saat Anda mendorongnya. Perbedaannya adalah bahwa test case bekerja sangat sempit dengan persyaratan kode Anda dan Anda harus menulisnya, sementara peringatan bekerja secara luas untuk standar yang masuk akal untuk hampir semua kode, dan mereka sangat murah hati disediakan oleh para peti mati yang membuat kompiler.
sumber
Peringatan tidak tetap akan , cepat atau lambat, akan menyebabkan kesalahan dalam kode Anda .
Debugging kesalahan segmentasi, misalnya, mengharuskan programmer untuk melacak root (penyebab) kesalahan, yang biasanya terletak di tempat sebelumnya dalam kode Anda daripada garis yang akhirnya menyebabkan kesalahan segmentasi.
Ini sangat tipikal bahwa penyebabnya adalah garis di mana kompiler mengeluarkan peringatan yang Anda abaikan, dan garis yang menyebabkan segmentasi kesalahan garis yang akhirnya menyebabkan kesalahan.
Memperbaiki peringatan mengarah ke memperbaiki masalah .. Klasik!
Peragaan di atas .. Pertimbangkan kode berikut:
yang ketika dikompilasi dengan bendera "Wextra" yang diteruskan ke GCC, memberikan:
yang bisa saya abaikan dan laksanakan kodenya .. Dan kemudian saya akan menyaksikan kesalahan segmentasi "grand", seperti yang dikatakan oleh profesor epicurus IP saya:
Untuk men-debug ini dalam skenario dunia nyata, orang akan mulai dari garis yang menyebabkan kesalahan segmentasi dan mencoba melacak apa akar penyebabnya. Mereka harus mencari apa yang telah terjadi
i
danstr
di dalam jumlah yang sangat besar itu kode di sana ...Hingga, suatu hari, mereka menemukan diri mereka dalam situasi di mana mereka menemukan yang
idx
digunakan tidak diinisialisasi, sehingga memiliki nilai sampah, yang menghasilkan pengindeksan string (cara) di luar batasnya, yang mengarah ke kesalahan segmentasi.Kalau saja mereka tidak mengabaikan peringatan itu, mereka akan segera menemukan bug!
sumber
str[idx]
" bukan "Oke, di manastr
danidx
ditentukan?`idx
adalah nilai yang Anda harapkan pada tes Anda (tidak terlalu tidak mungkin jika nilai yang diharapkan adalah 0), dan sebenarnya menunjuk pada beberapa data sensitif yang tidak boleh dicetak saat digunakan.Memperlakukan peringatan sebagai kesalahan hanyalah cara disiplin diri: Anda menyusun program untuk menguji fitur baru yang mengkilap itu, tetapi Anda tidak bisa sampai memperbaiki bagian yang ceroboh. Tidak ada informasi tambahan yang
Werror
disediakan, itu hanya menetapkan prioritas dengan sangat jelas:Benar-benar pola pikir yang penting, bukan alat. Keluaran diagnostik kompiler adalah alat. MISRA (untuk embedded C) adalah alat lain. Tidak masalah yang mana yang Anda gunakan, tetapi bisa dibilang peringatan kompiler adalah alat termudah yang bisa Anda dapatkan (hanya satu bendera untuk ditetapkan) dan rasio sinyal terhadap noise sangat tinggi. Jadi tidak ada alasan untuk tidak menggunakannya.
Tidak ada alat yang sempurna. Jika Anda menulis
const float pi = 3.14;
, sebagian besar alat tidak akan memberi tahu Anda bahwa Anda mendefinisikan π dengan presisi buruk yang dapat menyebabkan masalah di kemudian hari. Sebagian besar alat tidak akan menaikkan alisif(tmp < 42)
, bahkan jika sudah umum diketahui bahwa memberikan variabel nama yang tidak berarti dan menggunakan angka ajaib adalah cara untuk bencana dalam proyek-proyek besar. Anda harus memahami bahwa kode "tes cepat" apa pun yang Anda tulis hanyalah: tes, dan Anda harus menyelesaikannya sebelum melanjutkan ke tugas lain, sementara Anda masih melihat kekurangannya. Jika Anda membiarkan kode seperti itu, men-debug jika setelah Anda menghabiskan dua bulan menambahkan fitur baru akan jauh lebih sulit.Setelah Anda masuk ke pola pikir yang benar, tidak ada gunanya menggunakan
Werror
. Memiliki peringatan sebagai peringatan akan memungkinkan Anda mengambil keputusan berdasarkan informasi apakah masih masuk akal untuk menjalankan sesi debug yang akan Anda mulai, atau membatalkannya dan memperbaiki peringatan terlebih dahulu.sumber
clippy
alat linting untuk Rust akan benar-benar memperingatkan tentang konstanta "3.14". Ini sebenarnya contoh dalam dokumen . Tetapi seperti yang mungkin Anda tebak dari namanya,clippy
bangga menjadi orang yang sangat membantu.Sebagai seseorang yang bekerja dengan kode C tertanam lama, mengaktifkan peringatan kompiler telah membantu menunjukkan banyak kelemahan dan bidang untuk diselidiki ketika mengusulkan perbaikan. Dalam gcc memanfaatkan
-Wall
dan-Wextra
bahkan-Wshadow
telah menjadi penting. Saya tidak akan menghadapi setiap bahaya, tetapi saya akan membuat daftar beberapa yang muncul yang membantu menunjukkan masalah kode.Variabel tertinggal
Yang ini dapat dengan mudah menunjukkan pekerjaan yang belum selesai dan area yang mungkin tidak memanfaatkan semua variabel yang lulus yang bisa menjadi masalah. Mari kita lihat fungsi sederhana yang dapat memicu ini:
Hanya mengkompilasi ini tanpa -Wall atau -Wextra mengembalikan tidak ada masalah. -Wall akan memberi tahu Anda bahwa
c
itu tidak pernah digunakan:-Wextra juga akan memberi tahu Anda bahwa parameter Anda b tidak melakukan apa-apa:
Global Variable shadowing
Ini agak sulit dan tidak muncul sampai
-Wshadow
digunakan. Mari kita modifikasi contoh di atas untuk menambahkan saja, tetapi kebetulan ada global dengan nama yang sama dengan lokal yang menyebabkan banyak kebingungan ketika mencoba menggunakan keduanya.Ketika -Wshadow diaktifkan, mudah untuk menemukan masalah ini.
Memformat string
Ini tidak memerlukan flag tambahan apa pun di gcc, tetapi masih menjadi sumber masalah di masa lalu. Fungsi sederhana yang mencoba mencetak data, tetapi memiliki kesalahan pemformatan bisa terlihat seperti ini:
Ini tidak mencetak string karena bendera pemformatan salah dan gcc dengan senang hati akan memberi tahu Anda ini mungkin bukan yang Anda inginkan:
Ini hanya tiga dari banyak hal yang dapat diperiksa oleh kompiler untuk Anda. Ada banyak yang lain seperti menggunakan variabel tidak diinisialisasi yang ditunjukkan orang lain.
sumber
possible loss of precision
" dan "comparison between signed and unsigned
" peringatan. Saya merasa sulit untuk memahami berapa banyak "programmer" mengabaikan ini (pada kenyataannya, saya tidak begitu yakin mengapa mereka bukan kesalahan)sizeof
tidak ditandatangani, tetapi tipe integer standar ditandatangani. Thesizeof
jenis hasil,size_t
, biasanya digunakan untuk apapun yang berhubungan dengan jenis ukuran, seperti, misalnya, keselarasan atau array / count elemen wadah, sedangkan bilangan bulat pada umumnya dimaksudkan untuk digunakan sebagai "int
kecuali dinyatakan diperlukan". Mempertimbangkan berapa banyak orang yang diajarkan untuk menggunakannyaint
untuk beralih ke wadah mereka (dibandingkanint
dengansize_t
), menjadikannya sebuah kesalahan akan menghancurkan segalanya. ; PIni adalah jawaban spesifik untuk C, dan mengapa ini jauh lebih penting bagi C daripada yang lainnya.
Kode ini dikompilasi dengan peringatan . Apa yang seharusnya dan seharusnya merupakan kesalahan dalam hampir semua bahasa lain di planet ini (pembatasan bahasa assembly) adalah peringatan dalam C. Peringatan di C hampir selalu merupakan kesalahan dalam penyamaran. Peringatan harus diperbaiki, tidak ditekan.
Dengan
gcc
, kami melakukan ini sebagaigcc -Wall -Werror
.Ini juga merupakan alasan tingginya ketidaknyamanan tentang beberapa peringatan API MS yang tidak aman. Sebagian besar orang yang memprogram C telah mempelajari cara yang sulit untuk memperlakukan peringatan sebagai kesalahan dan hal-hal ini tampaknya bukan hal yang sama dan menginginkan perbaikan non-portabel.
sumber
PERINGATAN KOMPILER ADALAH TEMAN ANDA (tidak berteriak, huruf besar untuk penekanan).
Saya bekerja pada sistem warisan Fortran-77. Kompiler memberi tahu saya hal-hal yang berharga: argumen tipe data tidak cocok pada panggilan subrutin, menggunakan variabel lokal sebelum nilai telah ditetapkan ke dalam variabel, jika saya memiliki argumen variabel atau subrutin yang tidak digunakan. Ini hampir selalu merupakan kesalahan.
Menghindari posting lama: Ketika kode saya dikompilasi dengan bersih, 97% itu berfungsi. Orang lain yang bekerja dengan saya mengkompilasi dengan semua peringatan mati, menghabiskan berjam-jam atau berhari-hari di debugger, lalu meminta saya untuk membantu. Saya hanya mengkompilasi kode dengan peringatan menyala dan katakan padanya apa yang harus diperbaiki.
sumber
Anda harus selalu mengaktifkan peringatan kompiler karena kompilator sering dapat memberi tahu Anda apa yang salah dengan kode Anda. Untuk melakukan ini, Anda beralih
-Wall -Wextra
ke kompiler.Anda biasanya harus memperlakukan peringatan sebagai kesalahan karena peringatan biasanya menandakan bahwa ada yang salah dengan kode Anda. Namun, seringkali sangat mudah untuk mengabaikan kesalahan ini. Oleh karena itu, memperlakukan mereka sebagai kesalahan akan menyebabkan build gagal sehingga Anda tidak dapat mengabaikan kesalahan tersebut. Untuk memperlakukan peringatan sebagai kesalahan, sampaikan
-Werror
ke kompiler.sumber
Peringatan kompiler di C ++ sangat berguna untuk beberapa alasan.
1 - Ini memungkinkan untuk menunjukkan kepada Anda di mana Anda dapat melakukan kesalahan yang dapat berdampak pada hasil akhir operasi Anda. Sebagai contoh jika Anda tidak menginisialisasi variabel atau jika Anda meletakkan "=" bukannya "==" (hanya ada contoh)
2 - Ini juga memungkinkan untuk menunjukkan kepada Anda di mana kode Anda tidak sesuai dengan standar c ++. Ini berguna karena jika kode sesuai dengan standar aktual, akan mudah untuk memindahkan kode ke bentuk plat lain misalnya.
Secara umum, peringatan sangat berguna untuk menunjukkan kepada Anda di mana Anda memiliki kesalahan dalam kode Anda yang dapat mempengaruhi hasil algoritma Anda atau mencegah beberapa kesalahan saat pengguna akan menggunakan program Anda.
sumber
Mengabaikan peringatan berarti Anda meninggalkan kode ceroboh yang tidak hanya dapat menyebabkan masalah di masa depan untuk orang lain, tetapi juga akan membuat pesan kompilasi penting kurang diperhatikan oleh Anda. Semakin banyak output kompiler, semakin sedikit orang akan memperhatikan atau mengganggu. Lebih bersih lebih baik. Itu juga berarti Anda tahu apa yang Anda lakukan. Peringatan sangat tidak profesional, ceroboh, dan berisiko.
sumber
Saya pernah bekerja di perusahaan besar (Fortune 50) yang memproduksi peralatan pengujian elektronik.
Produk inti dari grup saya adalah program MFC yang, selama bertahun-tahun, menghasilkan ratusan peringatan. Yang diabaikan dalam hampir semua kasus.
Ini adalah mimpi buruk ketika bug terjadi.
Setelah posisi itu, saya cukup beruntung untuk dipekerjakan sebagai pengembang pertama dalam startup baru.
Saya mendorong kebijakan 'tidak ada peringatan' untuk semua bangunan, dengan tingkat peringatan penyusun diatur menjadi sangat berisik.
Praktik kami adalah menggunakan peringatan #pragma - push / disable / pop untuk kode yang yakin pengembang benar-benar baik, bersama dengan pernyataan log di tingkat debug, untuk berjaga-jaga.
Latihan ini berhasil bagi kami.
sumber
#pragma warning
tidak hanya menekan peringatan, itu melayani tujuan ganda dengan cepat berkomunikasi dengan programmer lain bahwa ada sesuatu yang disengaja dan tidak disengaja, dan bertindak sebagai tag pencarian untuk dengan cepat menemukan area yang berpotensi bermasalah ketika sesuatu rusak tetapi memperbaiki kesalahan / peringatan tidak memperbaikinya.Peringatan adalah kesalahan yang menunggu untuk terjadi. Jadi, Anda harus mengaktifkan peringatan kompiler dan merapikan kode Anda untuk menghapus peringatan apa pun.
sumber
Hanya ada satu masalah dengan memperlakukan peringatan sebagai kesalahan: Ketika Anda menggunakan kode yang berasal dari sumber lain (misalnya, perpustakaan mikro $ ** t, proyek sumber terbuka), mereka tidak melakukan tugasnya dengan benar, dan menyusun kode mereka menghasilkan banyak peringatan.
Saya selalu menulis kode saya sehingga tidak menghasilkan peringatan atau kesalahan, dan membersihkannya sampai kompilasi tanpa menghasilkan suara asing. Sampah yang harus saya kerjakan membuat saya terkejut, dan saya terkejut ketika saya harus membangun sebuah proyek besar dan menyaksikan arus peringatan yang berlalu di mana kompilasi seharusnya hanya mengumumkan file mana yang diprosesnya.
Saya juga mendokumentasikan kode saya karena saya tahu biaya perangkat lunak yang sebenarnya seumur hidup sebagian besar berasal dari pemeliharaan, bukan dari penulisan awalnya, tapi itu cerita yang berbeda ...
sumber
-Wall
dan Anda gunakan-Wall -Wextra
.Beberapa peringatan bisa berarti kemungkinan kesalahan semantik dalam kode atau kemungkinan UB. Misalnya
;
setelahif()
, variabel yang tidak digunakan, variabel global yang ditutup oleh lokal, atau perbandingan yang ditandatangani dan yang tidak ditandatangani. Banyak peringatan terkait dengan penganalisa kode statis dalam kompiler atau untuk pelanggaran standar ISO yang terdeteksi pada waktu kompilasi, yang "memerlukan diagnostik". Sementara kejadian-kejadian itu mungkin legal dalam satu kasus tertentu, mereka akan menjadi hasil dari masalah desain sebagian besar waktu.Beberapa kompiler, misalnya gcc, memiliki opsi baris perintah untuk mengaktifkan mode "peringatan sebagai kesalahan", itu adalah alat yang bagus, jika kejam, untuk mendidik pembuat kode pemula.
sumber
Fakta bahwa kompiler C ++ menerima kode kompilasi yang jelas menghasilkan perilaku yang tidak terdefinisi sama sekali adalah kelemahan utama dalam kompiler. Alasan mereka tidak memperbaiki ini adalah karena hal itu mungkin akan merusak beberapa build yang dapat digunakan.
Sebagian besar peringatan harus merupakan kesalahan fatal yang mencegah pembangunan selesai. Default untuk hanya menampilkan kesalahan dan tetap melakukan kesalahan adalah salah dan jika Anda tidak menimpanya untuk memperlakukan peringatan sebagai kesalahan dan meninggalkan beberapa peringatan maka kemungkinan Anda akan berakhir dengan crash dan melakukan hal-hal acak.
sumber
int i; if (fun1()) i=2; if (fun2()) i=3; char s="abcde"[i];
ini menunjukkan perilaku yang tidak terdefinisi jika dan hanya jika keduanyafun1()
danfun2()
dapat kembalifalse
pada eksekusi fungsi yang sama. Yang mana mungkin atau mungkin tidak benar, tetapi bagaimana cara memberitahu kompiler?Anda pasti harus mengaktifkan peringatan kompiler karena beberapa kompiler buruk dalam melaporkan beberapa kesalahan pemrograman umum, termasuk yang berikut: -
-> menginisialisasi variabel yang dilupakan -> mengembalikan nilai dari fungsi yang terlewatkan -> argumen sederhana dalam keluarga printf dan scanf tidak cocok dengan format string fungsi digunakan tanpa dideklarasikan sebelumnya, meskipun terjadi pada c saja
Jadi karena fungsi-fungsi ini dapat dideteksi dan dilaporkan, biasanya tidak secara default; jadi fitur ini harus diminta secara eksplisit melalui opsi kompiler.
sumber
Tenang saja: Anda tidak harus, itu tidak perlu. -Wall and -Werror dirancang oleh maniak kode-refactoring untuk diri mereka sendiri: itu diciptakan oleh pengembang kompiler untuk menghindari build yang ada setelah pembaruan kompiler di sisi pengguna . Fiturnya tidak ada apa-apanya, tetapi semua tentang keputusan untuk istirahat atau tidak untuk merusak build.
Ini sepenuhnya tergantung pada preferensi Anda untuk menggunakannya atau tidak. Saya menggunakannya sepanjang waktu karena membantu saya memperbaiki kesalahan saya.
sumber
-Wall and -Werror was designed by code-refactoring maniacs for themselves.
[rujukan?]-Wall
atau tidak-Werror
, dan hanya menanyakan apakah itu ide yang bagus. Yang mana, dari kalimat terakhir Anda, sepertinya Anda mengatakannya.