Apakah ada c ++ yang setara dengan Java
try {
...
}
catch (Throwable t) {
...
}
Saya mencoba men-debug kode Java / jni yang memanggil fungsi windows asli dan mesin virtual terus macet. Kode asli muncul dengan baik dalam pengujian unit dan hanya tampaknya macet ketika dipanggil melalui jni. Sebuah mekanisme penangkapan pengecualian generik akan terbukti sangat berguna.
Jawaban:
akan menangkap semua pengecualian C ++, tetapi harus dianggap sebagai desain yang buruk. Anda dapat menggunakan mekanisme current_exception baru c ++ 11, tetapi jika Anda tidak memiliki kemampuan untuk menggunakan c ++ 11 (sistem kode lama yang membutuhkan penulisan ulang), maka Anda tidak memiliki penunjuk pengecualian bernama yang akan digunakan untuk mendapatkan pesan atau nama . Anda mungkin ingin menambahkan klausa tangkapan terpisah untuk berbagai pengecualian yang dapat Anda tangkap, dan hanya menangkap semua yang ada di bagian bawah untuk merekam pengecualian yang tidak terduga. Misalnya:
sumber
Seseorang harus menambahkan bahwa seseorang tidak dapat menangkap "crash" dalam kode C ++. Mereka tidak melempar pengecualian, tetapi lakukan apa saja yang mereka suka. Ketika Anda melihat program macet karena mengatakan null-pointer dereference, itu melakukan perilaku yang tidak ditentukan. Tidak ada
std::null_pointer_exception
. Mencoba menangkap pengecualian tidak akan membantu di sana.Hanya untuk kasus seseorang membaca utas ini dan berpikir dia bisa mendapatkan penyebab crash program. Debugger seperti gdb harus digunakan sebagai gantinya.
sumber
try { .. } catch(...) { ... }
untuk menangkap menggunakan sinyal / sigaction, saya tidak akan menyebutnya "menangkap" :) Jika dalam penangan sinyal, relatif sulit bagi programmer untuk mengetahui di mana dalam kode crash terjadi (saya sedang berbicara tentang mendeteksi secara programatik), dibandingkan dengan mencoba / menangkap.Ini adalah cara Anda dapat merekayasa balik tipe pengecualian dari dalam
catch(...)
jika perlu (mungkin berguna saat menangkap yang tidak diketahui dari perpustakaan pihak ketiga) dengan GCC:dan jika Anda mampu menggunakan Boost Anda dapat membuat bagian tangkapan Anda lebih sederhana (di luar) dan berpotensi lintas platform
sumber
Perhatikan bahwa bagian
...
dalamcatch
adalah elipsis nyata, yaitu. tiga titik.Namun, karena pengecualian C ++ tidak selalu merupakan subkelas dari
Exception
kelas dasar , tidak ada cara untuk benar-benar melihat variabel pengecualian yang dilemparkan saat menggunakan konstruksi ini.sumber
catch
specifier dari placeholder kode yang ada di komentar (// ...
) yang jelas bukan sintaks C ++.tidak mungkin (dalam C ++) untuk menangkap semua pengecualian dengan cara yang portabel. Ini karena beberapa pengecualian bukan pengecualian dalam konteks C ++. Ini termasuk hal-hal seperti pembagian dengan kesalahan nol dan lain-lain. Dimungkinkan untuk meretas dan dengan demikian mendapatkan kemampuan untuk melemparkan pengecualian ketika kesalahan ini terjadi, tetapi itu tidak mudah dilakukan dan tentu saja tidak mudah untuk mendapatkan yang benar dengan cara yang portabel.
Jika Anda ingin menangkap semua pengecualian STL, Anda dapat melakukannya
Yang akan memungkinkan Anda menggunakan
e.what()
, yang akan mengembalikanconst char*
, yang dapat memberi tahu Anda lebih banyak tentang pengecualian itu sendiri. Ini adalah konstruk yang menyerupai konstruk Jawa, yang paling sering Anda tanyakan.Ini tidak akan membantu Anda jika seseorang cukup bodoh untuk melemparkan pengecualian yang tidak diwarisi darinya
std::exception
.sumber
Singkatnya, gunakan
catch(...)
. Namun, catatan yangcatch(...)
dimaksudkan untuk digunakan bersama denganthrow;
dasarnya:Ini adalah cara yang tepat untuk digunakan
catch(...)
.sumber
Foo
destruktor? Saya pikir itulah inti dari RAII. Namun, jika Anda memerlukan pointer keFoo
daripada hanya membuatFoo
di stack, maka Anda harus membungkus pointer di sesuatu yang lain yang dinyatakan pada stack.adalah mungkin untuk melakukan ini dengan menulis:
Tetapi ada risiko yang sangat tidak terlihat di sini: Anda tidak dapat menemukan jenis kesalahan yang tepat yang telah dilemparkan di
try
blok, jadi gunakan jenis inicatch
ketika Anda yakin bahwa tidak peduli apa pun jenis pengecualiannya, program harus tetap ada dengan cara yang didefinisikan dalamcatch
blok.sumber
Kamu bisa memakai
tapi itu sangat berbahaya. Dalam bukunya Debugging Windows , John Robbins menceritakan kisah perang tentang bug yang benar-benar jahat yang ditutupi oleh perintah catch (...). Anda jauh lebih baik menangkap pengecualian khusus. Tangkap apa pun yang menurut Anda dapat dicekal oleh blok percobaan Anda, tetapi biarkan kode tersebut melemparkan pengecualian lebih tinggi jika sesuatu yang benar-benar tidak terduga terjadi.
sumber
Biarkan saya sebutkan ini di sini: Jawa
mungkin TIDAK menangkap semua pengecualian! Sebenarnya saya pernah mengalami hal semacam ini sebelumnya, dan itu sangat memprovokasi; Pengecualian berasal dari Throwable. Jadi secara harfiah, untuk menangkap semuanya, Anda TIDAK ingin menangkap Pengecualian; Anda ingin menangkap Throwable.
Saya tahu ini kedengarannya menggelikan, tetapi ketika Anda telah menghabiskan beberapa hari mencoba mencari tahu dari mana "pengecualian tanpa tertangkap" berasal dari kode yang dikelilingi oleh blok coba ... tangkap (Pengecualian) "berasal, tetap dengan kamu.
sumber
catch(Exception)
mungkin tidak menangkap semua pengecualian di Jawa, Anda membuatnya dicampur dengan C # ... Java =catch(Thowable)
, C # =catch(Exception)
. Jangan sampai mereka bingung.CoderMalfunctionError
(yang sebenarnya adalahError
subclass Java nyata ... meskipun tidak berarti seperti apa terdengarnya.)Nah, jika Anda ingin menangkap semua pengecualian untuk membuat minidump misalnya ...
Seseorang melakukan pekerjaan di Windows.
Lihat http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus Dalam artikel itu, ia menjelaskan bagaimana ia menemukan cara menangkap semua jenis pengecualian dan ia memberikan kode yang berfungsi.
Berikut daftar yang bisa Anda tangkap:
Dan penggunaannya: CCrashHandler ch; ch.SetProcessExceptionHandlers (); // lakukan ini untuk satu utas ch.SetThreadExceptionHandlers (); // untuk setiap thred
Secara default, ini membuat minidump di direktori saat ini (crashdump.dmp)
sumber
Diragukan. Anda sudah tahu kode Anda rusak, karena mogok. Makan pengecualian mungkin menutupi ini, tetapi itu mungkin hanya akan menghasilkan bug yang lebih buruk, lebih halus.
Yang Anda inginkan adalah debugger ...
sumber
Bisakah Anda menjalankan aplikasi Java yang menggunakan JNI dari jendela konsol (luncurkan dari baris perintah java) untuk melihat apakah ada laporan apa pun yang mungkin telah terdeteksi sebelum JVM macet. Saat dijalankan secara langsung sebagai aplikasi Java window, Anda mungkin kehilangan pesan yang akan muncul jika Anda lari dari jendela konsol.
Kedua, dapatkah Anda mematikan implementasi JNI DLL Anda untuk menunjukkan bahwa metode di DLL Anda sedang dimasukkan dari JNI, Anda kembali dengan benar, dll?
Untuk berjaga-jaga jika masalahnya adalah salah penggunaan metode antarmuka JNI dari kode C ++, apakah Anda telah memverifikasi bahwa beberapa contoh JNI sederhana mengkompilasi dan bekerja dengan pengaturan Anda? Saya sedang berpikir khususnya menggunakan metode antarmuka JNI untuk mengkonversi parameter ke format C ++ asli dan mengubah hasil fungsi menjadi tipe Java. Berguna untuk mematikannya untuk memastikan bahwa konversi data berfungsi dan Anda tidak akan terpuruk dalam panggilan mirip COM ke antarmuka JNI.
Ada hal-hal lain untuk diperiksa, tetapi sulit untuk menyarankan tanpa mengetahui lebih lanjut tentang apa metode asli Java Anda dan apa yang coba dilakukan oleh implementasi JNI dari mereka. Tidak jelas bahwa menangkap pengecualian dari level kode C ++ terkait dengan masalah Anda. (Anda dapat menggunakan antarmuka JNI untuk mengubah kembali pengecualian sebagai Java, tetapi tidak jelas dari apa yang Anda berikan bahwa ini akan membantu.)
sumber
Untuk masalah sebenarnya tentang tidak dapat melakukan debug dengan benar pada program yang menggunakan JNI (atau bug tidak muncul saat menjalankannya di bawah debugger):
Dalam hal ini sering membantu untuk menambahkan pembungkus Java di sekitar panggilan JNI Anda (yaitu semua metode asli adalah pribadi dan metode publik Anda di kelas memanggil mereka) yang melakukan beberapa pemeriksaan kewarasan dasar (memeriksa bahwa semua "objek" dibebaskan dan "objek" tidak digunakan setelah membebaskan) atau sinkronisasi (hanya menyinkronkan semua metode dari satu DLL ke instance objek tunggal). Biarkan metode pembungkus java mencatat kesalahan dan melemparkan pengecualian.
Ini akan sering membantu untuk menemukan kesalahan nyata (yang secara mengejutkan sebagian besar dalam kode Java yang tidak mematuhi semantik fungsi yang disebut menyebabkan beberapa double-frees atau sejenisnya) lebih mudah daripada mencoba men-debug program Java paralel besar-besaran dalam sebuah debugger asli ...
Jika Anda tahu penyebabnya, simpan kode dalam metode pembungkus Anda yang menghindarinya. Lebih baik Anda memiliki metode pembungkus Anda melemparkan pengecualian daripada kode JNI Anda crash VM ...
sumber
Yah ini sangat tergantung pada lingkungan kompiler. gcc tidak menangkap ini. Visual Studio dan Borland terakhir yang saya gunakan lakukan.
Jadi kesimpulan tentang crash adalah bahwa itu tergantung pada kualitas lingkungan pengembangan Anda.
Spesifikasi C ++ mengatakan bahwa tangkapan (...) harus menangkap pengecualian, tetapi tidak dalam semua kasus.
Setidaknya dari apa yang saya coba.
sumber
Waspadalah
hanya menangkap pengecualian tingkat bahasa, pengecualian / kesalahan tingkat rendah lainnya seperti
Access Violation
danSegmentation Fault
tidak akan tertangkap.sumber