Dalam Kapan menggunakan C lebih dari C ++, dan C ++ lebih dari C? ada wrt pernyataan. untuk pengecualian ukuran kode / C ++:
Jerry menjawab (di antara poin-poin lain):
(...) cenderung lebih sulit untuk menghasilkan executable yang benar-benar kecil dengan C ++. Untuk sistem yang sangat kecil, Anda jarang menulis banyak kode, dan tambahan (...)
yang saya tanyakan mengapa itu terjadi, yang dijawab Jerry:
hal utama adalah bahwa C ++ termasuk penanganan exception, yang (setidaknya biasanya) menambahkan beberapa ukuran minimum ke executable. Sebagian besar kompiler akan memungkinkan Anda menonaktifkan penanganan pengecualian, tetapi ketika Anda melakukan hasilnya tidak cukup C ++ lagi. (...)
yang saya tidak ragu pada tingkat dunia nyata teknis.
Oleh karena itu saya tertarik (murni karena penasaran) untuk mendengar dari contoh dunia nyata di mana proyek memilih C ++ sebagai bahasa dan kemudian memilih untuk menonaktifkan pengecualian. (Bukan hanya sekadar "tidak menggunakan" pengecualian dalam kode pengguna, tetapi nonaktifkan mereka di kompiler, sehingga Anda tidak dapat membuang atau menangkap pengecualian.) Mengapa proyek memilih untuk melakukannya (masih menggunakan C ++ dan bukan C, tetapi tidak ada pengecualian) - apa alasannya (teknis)?
Tambahan: Bagi mereka yang ingin menguraikan jawaban mereka, alangkah baiknya untuk merinci bagaimana implikasi tanpa pengecualian ditangani:
- Koleksi STL (
vector
, ...) tidak berfungsi sebagaimana mestinya (kegagalan alokasi tidak dapat dilaporkan) new
tidak bisa melempar- Konstruktor tidak dapat gagal
sumber
Jawaban:
Hampir semua game konsol di luar sana ada di C ++ dengan pengecualian dinonaktifkan, bahkan hari ini. Selain itu, pengaturan default untuk kompiler C ++ menargetkan konsol tersebut. Terkadang beberapa fitur C ++ tidak dijamin berfungsi dengan benar pada kompiler-kompiler itu, seperti multiple inheritance (Saya sedang memikirkan kompiler default konsol yang sangat terkenal misalnya).
Juga, contoh lain adalah perangkat keras Arduino SDK usnig gcc tanpa kecuali diaktifkan di C ++, dan hal-hal lain seperti tidak disediakan STL .
Ada beberapa alasan teknis, baik atau buruk, apa pun, itu bukan saran saya tetapi alasan yang pernah saya dengar:
Saya pikir pengecualian bisa berguna bahkan di game tapi itu benar bahwa di game konsol itu tidak terlalu berguna.
Memperbarui:
Saya menambahkan contoh mengejutkan lain di sini: LLVM / CLang jangan gunakan pengecualian atau RTTI karena alasan berikut :
CLang terkenal dengan kecepatan kompilasi dan kesalahan eksplisit, tetapi juga salah satu kompiler langka yang memiliki kode yang benar-benar mudah diikuti.
sumber
Jerry mengatakan: ... hasilnya tidak cukup C ++ lagi , sementara metafora saya adalah bahwa hal itu adalah jelas C ++, hanya sedikit berbeda dialek karena program memanfaatkan bentuk-bentuk lain, konvensi, dan gaya tertulis.
Berikut adalah alasan utama saya untuk menonaktifkannya:
Kompatibilitas Biner
Batas lintas bahasa dan terjemahan tidak secara universal didefinisikan dengan baik, atau tidak ditentukan. Jika Anda ingin menjamin program Anda beroperasi dalam domain perilaku yang ditentukan, Anda harus mengkarantina pengecualian di titik keluar modul.
Ukuran yang Dapat Dieksekusi
Berikut adalah ukuran biner dari program bebas pengecualian yang saya tulis, dibuat tanpa dan dengan pengecualian yang diaktifkan:
Tanpa pengecualian:
Dengan pengecualian:
Pengingat: Itu adalah koleksi perpustakaan dan program yang mengandung nol lemparan / tangkapan. Compiler bendera tidak memungkinkan pengecualian dalam C ++ perpustakaan standar. Oleh karena itu, biaya di dunia nyata lebih dari 19% terlihat dalam contoh ini.
Kompiler: apple gcc4.2 + llvm. Ukuran dalam MB.
Kecepatan
Terlepas dari istilah "pengecualian biaya nol", mereka masih menambahkan beberapa biaya overhead bahkan ketika tidak ada yang melempar. Dalam kasus di atas, ini adalah program kritis kinerja (Pemrosesan Sinyal, Pembuatan, Penyajian, Konversi, dengan set / sinyal data besar, dll.). Pengecualian bukan fitur yang diperlukan dalam desain ini, sementara kinerja sangat penting.
Kebenaran Program
Sepertinya alasan aneh ... Jika melempar bukan pilihan, Anda harus menulis program yang relatif ketat, benar, teruji dengan baik untuk menjamin program Anda dieksekusi dengan benar, dan bahwa klien menggunakan antarmuka dengan benar (jika Anda memberi saya argumen yang buruk atau melakukan tidak memeriksa kode kesalahan, maka Anda layak mendapatkan UB). Hasil? Kualitas implementasi sangat meningkat dan masalah diperbaiki dengan cepat.
Kesederhanaan
Implementasi penanganan pengecualian sering tidak diperbarui. Mereka juga menambahkan banyak kompleksitas karena implementasi dapat memiliki banyak banyak sekuens keluar. Lebih mudah untuk membaca dan memelihara program yang sangat kompleks ketika mereka menggunakan sekumpulan kecil strategi keluar yang diketik dengan baik yang diketik dan ditangani oleh klien. Dalam kasus lain, implementasi mungkin dari waktu ke waktu menerapkan lebih banyak lemparan atau ketergantungan mereka dapat memperkenalkan mereka. Klien tidak dapat dengan mudah atau tepat mempertahankan terhadap semua pintu keluar ini. Saya menulis dan memperbarui banyak perpustakaan, sering ada evolusi dan peningkatan. Mencoba untuk menjaga agar semuanya tetap selaras dengan urutan keluar pengecualian (dalam basis kode besar) tidak akan menjadi penggunaan waktu yang baik, dan kemungkinan akan menambah banyak kebisingan dan cacat. Karena peningkatan kebenaran program dan lebih banyak tes,
Sejarah / Kode yang Ada
Dalam beberapa kasus, mereka tidak pernah diperkenalkan karena alasan historis. Basis kode yang ada tidak menggunakannya, mengubah program bisa memakan waktu bertahun-tahun dan membuatnya sangat jelek untuk dipelihara karena tumpang tindih dalam konvensi dan implementasi.
Kerugian
Tentu saja, ada kelemahannya, yang terbesar adalah: Incompatability (termasuk. Binary) dengan perpustakaan lain, dan fakta bahwa Anda harus mengimplementasikan sejumlah program yang baik agar sesuai dengan model ini.
sumber
malloc
pengembalian0
), pengalokasi memasukiwhile (1)
yang memiliki konteks switch, diikuti oleh upaya lain pada alokasi. Dalam basis kode ini, dulu yang baru melalui pengalokasi dapat mengembalikan 0, tetapi implementasi yang lebih baru telah berfungsi dengan baik. (lanjutan)Google tidak menyetujui pengecualian dalam Panduan Gaya C ++ mereka , sebagian besar karena alasan historis:
(Penekanan editor)
sumber
Qt hampir tidak pernah menggunakan pengecualian. Kesalahan dalam Qt ditandai dengan kode dan sinyal kesalahan. Alasan yang dinyatakan secara resmi adalah:
Saat ini, satu kritik umum terhadap Qt adalah bahwa pengecualian keamanannya tidak lengkap.
sumber
Symbian C ++ (digunakan pada beberapa ponsel Nokia) tidak menggunakan pengecualian, setidaknya tidak secara langsung, karena kompiler C ++ tidak dapat mengimplementasikannya dengan andal ketika Symbian pertama kali dikembangkan.
sumber
Saya / tidak pernah / menggunakan pengecualian. Ada sejumlah alasan untuk ini, tetapi dua alasan utama adalah bahwa saya tidak pernah membutuhkan mereka untuk menghasilkan kode yang kuat dan bahwa mereka mengurangi kinerja saat runtime.
Saya telah bekerja pada kode produksi yang menggunakan dan menonaktifkan pengecualian - kode yang memungkinkan pengecualian secara keseluruhan lebih buruk. Di beberapa tempat pengecualian digunakan untuk kontrol aliran asli daripada penanganan kesalahan, yang sangat berat, anti-kinerja, dan sulit untuk di-debug. Secara umum masalah debugging dalam pengecualian kode diisi lebih sulit daripada dalam kode bebas pengecualian - sebagian turun ke tumpukan dan kesulitan intrinsik dari mekanisme pengecualian, tetapi lebih dari itu karena kode malas yang didorong sebagai hasil dari memiliki penanganan eksepsi yang tersedia.
Tidak ada yang salah dengan pengecualian itu sendiri / jika Anda tidak peduli dengan kinerja / dan tidak punya waktu untuk melakukan sesuatu dengan benar - mereka adalah fitur bahasa untuk penanganan kesalahan dan pengganti yang baik untuk mekanisme penanganan kesalahan yang tepat. Namun, hampir selalu / lebih baik / cara untuk menangani kesalahan - seperti dengan logika Anda sendiri (sulit untuk diuraikan tentang ini - itu hampir masuk akal). Jika ini bukan kesalahan Anda, tetapi berasal dari perpustakaan (mis. Perpustakaan standar) maka Anda harus menghormati pilihan pengecualian atau mengalami kerusakan, tapi saya selalu mempertanyakan pilihan itu. Saya belum pernah melihat situasi di mana pengecualian sebenarnya adalah solusi terbaik.
Pernyataan lebih debuggable, kode kesalahan kurang berat ... antara keduanya, jika digunakan dengan benar, Anda lebih mudah membaca, men-debug, dan memelihara kode yang lebih cepat. Menang semua ...
sumber
Dalam standar pengkodean Joint Strike Fighter C ++ oleh Bjarne et. al., pengecualian dilarang, karena persyaratan real-time jet tempur yang keras.
Dikutip dari FAQ C ++ Bjarne .
Ingat, C ++ mungkin menjalankan berbagai perangkat lunak terluas dari semua bahasa ...
sumber
Ini agak penting dalam desain perpustakaan C ++. Sering kali dengan antarmuka-C itu agak tidak enak untuk membuang pengecualian dari perpustakaan pihak ke-3 Anda ke klien. Intinya adalah bahwa jika perpustakaan Anda melempar, Anda memotong satu set klien yang akan menggunakannya, mengingat bahwa itu memiliki jaminan tanpa-lemparan (untuk alasan apa pun yang dimiliki klien untuk pembatasan pengecualian).
Secara pribadi saya telah melihat pengecualian dilecehkan ketika tim disuruh "melempar pengecualian" setiap kali sesuatu yang tidak begitu mengerikan terjadi. Tentu saja Anda melihat kesalahan di sini - pengecualian dilemparkan ke dalam kode sebelum ada yang tahu apa yang harus dilakukan dengannya. Proyek itu mengalami beberapa crash karena deep-throws ini akan keluar sesekali.
sumber
Mungkin dalam hal ini, ada baiknya menyebutkan Embedded C ++ . Embedded C ++ adalah varian dari C ++ yang dirancang (cukup jelas) untuk sistem embedded. Ini pada dasarnya bagian yang tepat dari C ++, dengan (antara lain) template, ruang nama, dan penanganan pengecualian dihapus.
Saya harus menambahkan bahwa sementara EC ++ membuat sedikit percikan ketika masih baru, mereka tampaknya sebagian besar sudah cukup sepi. Saya tidak yakin apakah orang kehilangan minat, atau upaya pertama mereka begitu sempurna sehingga tidak ada yang melihat alasan untuk mengacaukannya selama satu dekade atau lebih.
<closed captioning for the humor impaired>Yeah, right!</closed captioning>
sumber
Contoh yang bagus adalah pemrograman mode kernel.
Anda dapat menggunakan C ++ di sana untuk kode pembersih tetapi tanpa pengecualian. Tidak ada perpustakaan runtime untuk mereka dan penanganan pengecualian menggunakan memori stack terlalu banyak yang sangat terbatas di kernel (saya bereksperimen dengan pengecualian C ++ di kernel Windows NT dan pengecualian melempar dan melepaskan makan setengah dari stack yang tersedia - sangat mudah untuk mendapatkan stack overflow dan crash seluruh sistem).
Biasanya Anda menentukan operator
new
dandelete
operator Anda. Saya juga menemukanplacement new
referensi nilai a dan c ++ 11 yang sangat berguna . STL atau pustaka mode pengguna C ++ lainnya yang bergantung pada pengecualian dapat digunakan.sumber
Ketika Anda mencoba untuk menjaga memori yang dapat dieksekusi. Biasanya dilakukan pada sistem embedded (atau seluler). Untuk aplikasi desktop namun tidak diperlukan di server, ini mungkin dipertimbangkan jika Anda ingin ram sebanyak mungkin untuk server web atau untuk sql.
sumber