Apa itu debugger dan bagaimana hal itu dapat membantu saya mendiagnosis masalah?

107

Ini dimaksudkan sebagai pertanyaan dengan tujuan umum untuk membantu pemrogram baru yang memiliki masalah dengan program, tetapi tidak tahu cara menggunakan debugger untuk mendiagnosis penyebab masalah.

Pertanyaan ini mencakup tiga kelas pertanyaan yang lebih spesifik:

  • Ketika saya menjalankan program saya, itu tidak menghasilkan keluaran yang saya harapkan dari masukan yang saya berikan.
  • Ketika saya menjalankan program saya, program itu macet dan memberi saya jejak tumpukan. Saya telah memeriksa pelacakan tumpukan , tetapi saya masih tidak tahu penyebab masalahnya karena pelacakan tumpukan tidak memberi saya informasi yang cukup.
  • Ketika saya menjalankan program saya, itu macet karena kesalahan segmentasi (SEGV).
Raedwald
sumber
3
Kerja bagus - sebaiknya juga memiliki T&J "buka" terkait untuk teknik debugging , misalnya menggunakan debugger, alat debug lainnya (misalnya valgrind), printf strategis, uji stres, bagi dan taklukkan, dll.
Paul R
1
Saya setuju dengan @PaulR, FAQ harus berisi hal-hal seperti ini.
Nicu Stiurca

Jawaban:

73

Debugger adalah program yang dapat memeriksa status program Anda saat program Anda berjalan. The sarana teknis menggunakan untuk melakukan hal ini tidak penting untuk memahami dasar-dasar bagaimana menggunakan debugger. Anda dapat menggunakan debugger untuk menghentikan eksekusi program Anda ketika program mencapai tempat tertentu dalam kode Anda, kemudian memeriksa nilai variabel dalam program. Anda dapat menggunakan debugger untuk menjalankan program Anda dengan sangat lambat, satu baris kode dalam satu waktu (disebut langkah tunggal ), saat Anda memeriksa nilai variabelnya.

Menggunakan debugger adalah keterampilan dasar yang diharapkan

Debugger adalah alat yang sangat ampuh untuk membantu mendiagnosis masalah dengan program. Dan debugger tersedia untuk semua bahasa pemrograman praktis. Oleh karena itu, dapat menggunakan debugger dianggap sebagai keterampilan dasar dari setiap programmer profesional atau peminat. Dan menggunakan debugger sendiri dianggap pekerjaan dasar yang harus Anda lakukan sendiri sebelum meminta bantuan orang lain. Karena situs ini ditujukan untuk pemrogram profesional dan antusias, dan bukan situs helpdesk atau situs bimbingan, jika Anda memiliki pertanyaan tentang masalah dengan program tertentu, tetapi belum menggunakan debugger, pertanyaan Anda kemungkinan besar akan ditutup dan ditolak. Jika Anda terus bertanya-tanya seperti itu, pada akhirnya Anda akan diblokir untuk memposting lebih banyak lagi.

Bagaimana debugger dapat membantu Anda

Dengan menggunakan debugger Anda dapat menemukan apakah suatu variabel memiliki nilai yang salah, dan di mana dalam program Anda nilainya berubah menjadi nilai yang salah.

Dengan menggunakan satu langkah, Anda juga dapat mengetahui apakah aliran kontrol seperti yang Anda harapkan. Misalnya, apakah sebuah ifcabang dieksekusi seperti yang Anda harapkan.

Catatan umum tentang penggunaan debugger

Spesifikasi penggunaan debugger bergantung pada debugger dan, pada tingkat yang lebih rendah, bahasa pemrograman yang Anda gunakan.

  • Anda dapat memasang debugger ke proses yang sudah menjalankan program Anda. Anda dapat melakukannya jika program Anda macet.

  • Dalam praktiknya, seringkali lebih mudah untuk menjalankan program Anda di bawah kendali debugger sejak awal.

  • Anda menunjukkan di mana program Anda harus berhenti mengeksekusi dengan menunjukkan file kode sumber dan nomor baris dari baris di mana eksekusi harus berhenti, atau dengan menunjukkan nama metode / fungsi di mana program harus berhenti (jika Anda ingin berhenti sebagai segera setelah eksekusi memasuki metode). Sarana teknis yang digunakan debugger untuk menyebabkan program Anda berhenti disebut breakpoint dan proses ini disebut menetapkan breakpoint .

  • Sebagian besar debugger modern adalah bagian dari IDE dan memberi Anda GUI yang mudah digunakan untuk memeriksa kode sumber dan variabel program Anda, dengan antarmuka tunjuk-dan-klik untuk menyetel breakpoint, menjalankan program Anda, dan melangkah satu kali.

  • Menggunakan debugger bisa sangat sulit kecuali program Anda dapat dijalankan atau file bytecode menyertakan informasi simbol debugging dan referensi silang ke kode sumber Anda. Anda mungkin harus mengkompilasi (atau mengkompilasi ulang) program Anda sedikit berbeda untuk memastikan bahwa informasi ada. Jika compiler melakukan pengoptimalan ekstensif, referensi silang tersebut bisa membingungkan. Oleh karena itu, Anda mungkin harus mengkompilasi ulang program Anda dengan pengoptimalan dimatikan .

Raedwald
sumber
4
Ini tidak lengkap karena melewatkan debugger terpenting, yang berpotensi mengurangi jumlah pertanyaan di Stackoverflow dengan sangat signifikan (saya perkirakan setidaknya 20%) - debugger javascript: firebug, Chrome, Firefox, IE9 + debugger terintegrasi , IE8- Visual Studio, dll.
slebetman
1
Juga untuk node.js - inspektur node. Tetapi pemrogram node.js tidak mengajukan pertanyaan dasar dan / atau perbaiki-kode-saya sebanyak pemrogram javascript umum.
slebetman
40

Saya ingin menambahkan bahwa debugger tidak selalu merupakan solusi sempurna, dan tidak harus selalu menjadi solusi masuk ke debugging. Berikut beberapa kasus saat debugger mungkin tidak berfungsi untuk Anda:

  • Bagian dari program Anda yang gagal sangat besar (modularisasi yang buruk, mungkin?) Dan Anda tidak yakin harus mulai dari mana melangkah melalui kode. Melangkahi semua itu mungkin terlalu memakan waktu.
  • Program Anda menggunakan banyak callback dan metode kontrol aliran non-linier lainnya, yang membuat debugger bingung saat Anda melewatinya.
  • Program Anda multi-threaded. Atau lebih buruk lagi, masalah Anda disebabkan oleh kondisi balapan.
  • Kode yang memiliki bug di dalamnya berjalan berkali-kali sebelum rusak. Ini bisa menjadi sangat bermasalah di loop utama, atau lebih buruk lagi, di mesin fisika, di mana masalahnya bisa berupa numerik. Bahkan menyetel breakpoint, dalam hal ini, hanya akan membuat Anda memukulnya berkali-kali, dengan bug tidak muncul.
  • Program Anda harus berjalan secara real-time. Ini adalah masalah besar untuk program yang terhubung ke jaringan. Jika Anda menyiapkan breakpoint dalam kode jaringan Anda, ujung lainnya tidak akan menunggu Anda untuk melangkah maju, itu hanya akan menghabiskan waktu. Program yang mengandalkan jam sistem, misalnya game dengan frameskip, juga tidak jauh lebih baik.
  • Program Anda melakukan beberapa bentuk tindakan merusak, seperti menulis ke file atau mengirim email, dan Anda ingin membatasi berapa kali Anda perlu menjalankannya.
  • Anda dapat mengetahui bahwa bug Anda disebabkan oleh kesalahan nilai yang tiba di fungsi X, tetapi Anda tidak tahu dari mana nilai ini berasal. Harus menjalankan program, lagi dan lagi, mengatur breakpoints semakin jauh ke belakang, bisa menjadi masalah besar. Apalagi jika fungsi X dipanggil dari banyak tempat di seluruh program.

Dalam semua kasus ini, menghentikan program Anda secara tiba-tiba dapat menyebabkan hasil akhir berbeda, atau melangkah secara manual untuk mencari satu baris di mana bug disebabkan terlalu merepotkan. Ini sama-sama dapat terjadi baik bug Anda adalah perilaku yang salah, atau crash. Misalnya, jika kerusakan memori menyebabkan kerusakan, pada saat kerusakan terjadi, itu terlalu jauh dari tempat kerusakan memori pertama kali terjadi, dan tidak ada informasi berguna yang tersisa.

Jadi apa saja alternatifnya?

Paling sederhana hanyalah pencatatan dan pernyataan. Tambahkan log ke program Anda di berbagai titik, dan bandingkan apa yang Anda dapatkan dengan apa yang Anda harapkan. Misalnya, lihat apakah fungsi yang menurut Anda ada bug dipanggil. Lihat apakah variabel di awal metode sesuai dengan perkiraan Anda. Tidak seperti breakpoint, tidak masalah jika ada banyak baris log di mana tidak ada hal khusus yang terjadi. Anda cukup mencari melalui log sesudahnya. Setelah Anda mencapai garis log yang berbeda dari yang Anda harapkan, tambahkan lebih banyak di area yang sama. Persempit semakin jauh, hingga cukup kecil untuk dapat mencatat setiap baris di area yang disadap.

Pernyataan dapat digunakan untuk menjebak nilai yang salah saat terjadi, daripada setelah memiliki efek yang terlihat oleh pengguna akhir. Semakin cepat Anda menangkap nilai yang salah, semakin dekat Anda dengan garis yang memproduksinya.

Tes refaktor dan unit. Jika program Anda terlalu besar, mungkin bermanfaat untuk mengujinya satu kelas atau satu fungsi pada satu waktu. Berikan masukan, dan lihat keluarannya, dan lihat mana yang tidak seperti yang Anda harapkan. Mampu mempersempit bug dari seluruh program menjadi satu fungsi dapat membuat perbedaan besar dalam waktu debugging.

Jika terjadi kebocoran memori atau hentakan memori, gunakan alat yang sesuai yang dapat menganalisis dan mendeteksi ini pada waktu proses. Mampu mendeteksi di mana korupsi sebenarnya terjadi adalah langkah pertama. Setelah ini, Anda dapat menggunakan log untuk kembali ke tempat nilai yang salah dimasukkan.

Ingatlah bahwa debugging adalah proses mundur. Anda mendapatkan hasil akhirnya - bug - dan temukan penyebabnya, yang mendahuluinya. Ini tentang bekerja mundur dan, sayangnya, debugger hanya melangkah maju. Di sinilah logging dan analisis postmortem yang baik dapat memberi Anda hasil yang jauh lebih baik.

SlugFiller
sumber
10
Ini akan menjadi jawaban yang bagus ... untuk pertanyaan yang berbeda. Itu adalah jawaban yang buruk untuk pertanyaan ini . Mungkin Anda harus mengajukan pertanyaan itu dan memposting ini sebagai balasannya.
Raedwald
10
Pertanyaan sebenarnya dideskripsikan sebagai "bantu pemrogram baru yang memiliki masalah dengan program", "program tersebut tidak menghasilkan keluaran yang saya harapkan" dan "Saya telah memeriksa jejak tumpukan, tetapi saya masih tidak tahu penyebab masalahnya" . Semuanya dibantu oleh jawaban ini. Selain itu, saat menjelaskan apa yang dilakukan debugger, sama pentingnya untuk menjelaskan apa yang tidak dilakukannya.
SlugFiller
5
Jawaban yang bagus. Saya selalu menggunakan debugger sebagai alat utama untuk menemukan bug. Tapi sekarang saya bekerja dalam sebuah proyek di mana komponen infrastruktur besar menggunakan banyak utas dan banyak kode jaringan (klien / server) dan perhatikan bahwa debugger adalah hal terakhir yang membantu saya. Anda telah menyebutkan banyak hal di mana Anda harus benar-benar menggunakan alat yang berbeda daripada mengandalkan debugger lama Anda yang baik (paling penting: logging).
Tim Schmelter
"Anda dapat mengetahui bahwa bug Anda disebabkan oleh kesalahan nilai yang tiba di fungsi X tetapi Anda tidak tahu dari mana nilai ini berasal" Ini sangat sulit untuk di-debug. Bagaimana Anda biasanya memperbaiki sesuatu seperti itu?
Ayxan Haqverdili
3
@Ayxan Sampai batas tertentu, jika Anda telah berhasil membuat fungsi berhenti pada suatu pernyataan, Anda bisa menggunakan tumpukan panggilan untuk mendapatkan pemanggil. Tetapi itu saja tidak memberi Anda sumber nilai, karena nilainya kemungkinan besar berasal dari baris sebelumnya. Anda pada dasarnya harus mengikuti nilainya kembali, melalui berbagai variabel yang dilaluinya. Jika Anda memiliki ide yang bagus tentang jalur yang diambil data, Anda dapat membuat sekumpulan cetakan log, dan mencoba mempersempit tempat yang "salah". Jika tidak, pada dasarnya Anda memerlukan program terpisah (mereproduksi kesalahan) untuk setiap langkah mundur.
SlugFiller