Jalankan Aplikasi di GDB Hingga Terjadi Pengecualian

102

Saya sedang mengerjakan aplikasi multithread, dan saya ingin men-debugnya menggunakan GDB.

Masalahnya adalah, salah satu utas saya terus mati dengan pesan:

pure virtual method called
terminate called without an active exception
Abort

Saya tahu penyebab pesan itu, tetapi saya tidak tahu di mana di utas saya pesan itu muncul. Pelacakan balik akan sangat membantu.

Saat saya menjalankan aplikasi saya di GDB, aplikasi akan berhenti setiap kali utas ditangguhkan atau dilanjutkan. Saya ingin aplikasi saya terus berjalan secara normal sampai salah satu utas mati dengan pengecualian itu, pada titik mana semuanya harus dihentikan sehingga saya bisa mendapatkan pelacakan balik.

Ankur Sethi
sumber
Sinyal apa yang dilaporkan GDB saat dijeda? Anda harus dapat menjalankan perintah sepertihandle SIGUSR1 pass noprint nostop
Hasturkun

Jawaban:

147

Anda dapat mencoba menggunakan "catchpoint" ( catch throw) untuk menghentikan debugger pada titik di mana pengecualian dibuat.

Kutipan berikut dari manual gdb menjelaskan fitur catchpoint.


5.1.3 Mengatur catchpoint

Anda dapat menggunakan catchpoint agar debugger berhenti untuk jenis acara program tertentu, seperti pengecualian C ++ atau pemuatan pustaka bersama. Gunakan perintah catch untuk mengatur catchpoint.

  • acara tangkap

    Berhenti ketika acara terjadi. acara dapat berupa salah satu dari berikut ini:

    • melemparkan

      Pelepasan pengecualian C ++.

    • menangkap

      Penangkapan pengecualian C ++.

    • eksekutif

      Panggilan ke eksekutif. Ini saat ini hanya tersedia untuk HP-UX.

    • garpu

      Panggilan ke garpu. Ini saat ini hanya tersedia untuk HP-UX.

    • vfork

      Panggilan ke vfork. Ini saat ini hanya tersedia untuk HP-UX.

    • memuat atau memuat libname

      Pemuatan dinamis dari setiap pustaka bersama, atau pemuatan nama perpustakaan. Ini saat ini hanya tersedia untuk HP-UX.

    • membongkar atau membongkar libname

      Pembongkaran perpustakaan bersama yang dimuat secara dinamis, atau pembongkaran libname perpustakaan. Ini saat ini hanya tersedia untuk HP-UX.

  • acara tcatch

    Tetapkan titik temu yang diaktifkan hanya untuk satu perhentian. Catchpoint secara otomatis dihapus setelah kejadian pertama kali tertangkap.

Gunakan info breakperintah untuk membuat daftar catchpoints saat ini.

Saat ini ada beberapa batasan untuk penanganan pengecualian C ++ (catch throw dan catch catch) di GDB:

  • Jika Anda memanggil suatu fungsi secara interaktif, GDB biasanya mengembalikan kontrol kepada Anda saat fungsi tersebut selesai dijalankan. Namun, jika panggilan memunculkan pengecualian, panggilan tersebut dapat melewati mekanisme yang mengembalikan kontrol kepada Anda dan menyebabkan program Anda dibatalkan atau terus berjalan hingga mencapai breakpoint, menangkap sinyal yang didengarkan oleh GDB, atau keluar. Ini adalah kasusnya bahkan jika Anda menetapkan catchpoint untuk pengecualian; catchpoints pada pengecualian dinonaktifkan dalam panggilan interaktif.

  • Anda tidak dapat mengajukan pengecualian secara interaktif.

  • Anda tidak dapat menginstal penangan pengecualian secara interaktif.

Terkadang catch bukanlah cara terbaik untuk men-debug penanganan pengecualian: jika Anda perlu tahu persis di mana pengecualian dimunculkan, lebih baik berhenti sebelum pengendali pengecualian dipanggil, karena dengan cara itu Anda dapat melihat tumpukan sebelum pelepasan apa pun terjadi. Jika Anda menetapkan breakpoint di penangan pengecualian, mungkin tidak mudah untuk mengetahui di mana pengecualian itu dimunculkan.

Untuk berhenti tepat sebelum penangan pengecualian dipanggil, Anda memerlukan pengetahuan tentang implementasinya. Dalam kasus GNU C ++, pengecualian dimunculkan dengan memanggil fungsi library bernama __raise_exception yang memiliki antarmuka ANSI C berikut:

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

Untuk membuat debugger menangkap semua pengecualian sebelum pelepasan tumpukan terjadi, setel breakpoint pada __raise_exception (lihat bagian Breakpoints; watchpoints; dan pengecualian).

Dengan breakpoint bersyarat (lihat bagian Kondisi break) yang bergantung pada nilai id, Anda bisa menghentikan program Anda saat pengecualian tertentu dimunculkan. Anda dapat menggunakan beberapa breakpoint bersyarat untuk menghentikan program Anda ketika salah satu dari sejumlah pengecualian dimunculkan.

Dan
sumber
Anda juga dapat menentukan jenis pengecualian untuk ditangkap, mis catch throw std::runtime_exception.
scai
5

Tetapkan breakpoint pada __pure_virtual

Steve Folly
sumber
Dalam jawaban @JeffreyHill, sekarang disebut __cxa_pure_virtual. Saya tidak tahu bagaimana cara memeriksanya, jadi saya tidak ingin mengedit jawabannya. Saya tidak bermaksud untuk down-vote, tapi jawabannya bisa saja salah sekarang dan harus diedit oleh seseorang yang tahu apa yang benar.
Philipp Claßen
5

FWIW, rupanya, di gcc 4.1, nama fungsi yang sesuai telah berubah dan kita harus menetapkan titik putus di fungsi ini.

__cxa_pure_virtual

Jeffrey Hill
sumber
0

Hanya di bawah satu yang berhasil untuk saya dengan gdb 8.3:

break _Unwind_RaiseException

"catch throw" atau "break __cxx_throw" tidak berhasil untuk saya.

soumeng78
sumber