Katakanlah Anda tidak memiliki debugger yang tersedia, apa yang akan menjadi pendekatan yang efektif untuk kode debug yang tidak berfungsi (seperti yang diharapkan)?
Katakanlah Anda tidak memiliki debugger yang tersedia, apa yang akan menjadi pendekatan yang efektif untuk kode debug yang tidak berfungsi (seperti yang diharapkan)?
Jawaban:
Ada sejumlah teknik:
Penebangan. Jika Anda tidak punya akses file, masuk ke konsol serial, atau perangkat output apa pun yang tersedia. Adalah ide yang baik untuk selalu menulis kode Anda dengan log in, memungkinkan kompilasi bersyarat untuk level logging yang berbeda, dari 'tidak ada' menjadi 'overbloated'.
Memotongnya. Kecualikan bagian-bagian kode Anda di sekitar titik bug yang dicurigai satu per satu, dan analisis apa yang telah Anda lakukan ketika bug menghilang.
Pernyataan atau kontrak. Merupakan ide bagus untuk mengisikan kode Anda dengan menegaskan dari awal. Mereka tidak hanya membantu dengan debugging, tetapi juga berfungsi sebagai dokumentasi tambahan untuk kode Anda.
Mirip dengan 2. - ubah input Anda dan ganti kode kecuali bug tersebut hilang atau ubah perilakunya. Ini sering merupakan ide yang baik untuk bermain dengan berbagai level optimisasi (jika Anda mengkode dalam C atau C ++), karena bug yang berhubungan dengan pointer cenderung sangat fluktuatif dalam perilaku mereka.
Versi otomatis 3. - gunakan kode yang diinstrumentasi, misalnya, jalankan biner di bawah valgrind.
Dan tentu saja ada lebih banyak alat dan trik, tergantung pada sifat lingkungan eksekusi Anda dan kode Anda.
Dapatkan seorang kolega dan jelaskan masalahnya secara detail saat Anda berjalan melewati kode yang merepotkan langkah demi langkah.
Sering kali tindakan menjelaskan menjelaskannya kepada kolega Anda atau diri Anda sendiri.
Apakah ada sistem logging untuk mengelola hasil program? Apakah setidaknya ada konsol untuk dicetak atau file yang dapat Anda tulis? Menggunakan konsol atau file log adalah cara Anda dapat melakukan debug tanpa debugger. Berikan input pada program agar Anda tahu apa yang seharusnya menjadi output, kemudian verifikasi bahwa output bekerja dan pastikan logging Anda memberi Anda banyak detail dari proses. Kemudian coba dengan input yang memberikan output yang salah. mudah-mudahan, log akan memberi Anda jejak terperinci dari apa yang salah.
Tergantung. Apakah itu berhasil sebelumnya? Jika kode yang digunakan untuk bekerja tiba-tiba rusak, maka Anda harus sangat hati-hati memeriksa perubahan terbaru.
1) Lakukan apa yang perlu Anda lakukan untuk membuat bug 100% dapat diproduksi kembali, atau hampir 100% yang Anda bisa
2) Lacak kembali masalahnya, menggunakan printf () atau fasilitas logging lainnya. Ini adalah seni, dan itu tergantung pada sifat bug.
Jika Anda sama sekali tidak tahu tentang lokasi bug, tetapi misalnya Anda tahu suatu kondisi menjadi salah di beberapa titik (keadaan program rusak - sebut saja isBroken ()), Anda dapat melakukan pencarian menelusuri / partisi untuk mencari tahu lokasi masalahnya. Misalnya, catat nilai isBroken () di awal di akhir metode utama:
void doSomething (void)
{
printf("START doSomething() : %d\n", isBroken());
doFoo();
doBar();
printf("END doSomething() : %d\n", isBroken());
}
Jika dalam log Anda lihat
START doSomething() : 0
END doSomething() : 1
Anda tahu ada yang salah di sana. Jadi, Anda menghapus semua kode logging lainnya, dan coba versi baru ini:
void doSomething (void)
{
printf("START doSomething() : %d\n", isBroken());
doFoo();
printf("AFTER doFoo() : %d\n", isBroken());
doBar();
printf("END doSomething() : %d\n", isBroken());
}
Sekarang dalam log Anda mungkin melihat ini
START doSomething() : 0
AFTER doFoo() : 0
END doSomething() : 1
Jadi sekarang Anda tahu doBar () memicu bug, dan Anda dapat mengulangi prosedur di atas di doBar (). Idealnya, Anda akan mempersempit kesalahan menjadi satu baris.
Tentu saja ini dapat membantu Anda mengungkapkan gejala bug dan bukan penyebab root - misalnya, Anda menemukan pointer NULL yang tidak boleh NULL, tetapi mengapa? Anda kemudian dapat login lagi, tetapi memeriksa kondisi "rusak" yang berbeda.
Jika Anda mengalami kerusakan alih-alih keadaan yang rusak, ini kurang lebih sama - baris terakhir dari log memberi Anda petunjuk tentang di mana hal-hal rusak.
Setelah jawaban lain gagal , selalu ada debugging pencarian biner :
Catatan: jelas, teknik ini hanya berfungsi jika Anda dapat mereproduksi masalah dengan andal.
'"Alat debugging paling efektif masih dipikirkan dengan cermat, ditambah dengan pernyataan cetak yang ditempatkan dengan bijaksana." - Brian Kernighan 'Pada hari itu mungkin benar! Metode yang paling efektif adalah dengan melihat unit test tetapi tebakan saya adalah Anda tidak memilikinya.
Itu tergantung bug.
Jika bug adalah jenis 'mengapa kode melakukan A', maka dapat bermanfaat untuk menguji pemahaman Anda sendiri tentang kode di sekitar lokasi 'kode melakukan A'. Perkenalkan kode baru yang Anda harapkan menghasilkan bug baru (kode ini harus membuatnya menjadi B, ini harus membuatnya menjadi C). Saya biasanya dengan cepat menemukan beberapa kode baru yang menghasilkan perilaku yang tidak saya harapkan. Lalu saya menunggu dengan sabar sementara pikiran saya membangun model mental yang diperbarui dari perilaku kode sehingga perubahan terakhir masuk akal, dan kemudian perubahan model mental itu biasanya menjelaskan mengapa kode itu melakukan A.
Kasus kedua telah dibahas secara rinci di sini. Di mana Anda telah mewarisi kode, tidak memiliki model mental yang solid tentang cara kode bekerja, tidak memiliki ide yang baik tentang lokasi spesifik bug, dll. Dalam hal ini, menelusuri / membagi-dan- metode menaklukkan dengan pernyataan cetak dapat bekerja. Dan jika itu di bawah kendali sumber, pastikan untuk memeriksa perubahan kode terbaru.
Memperluas pada "Alat debugging paling efektif masih dipikirkan dengan cermat, ditambah dengan pernyataan cetak yang ditempatkan dengan bijaksana."
Pertama, coba persempit saat bug terjadi. Jadikan gejala yang dapat diamati pengguna dapat diamati sistem. (katakanlah, beberapa string berubah menjadi omong kosong, tambahkan loop yang polling konten skrip dan memicu debug Anda saat itu berubah.) Tentu saja jika kesalahannya adalah crash, tambahkan penanganan segfault.
Kemudian coba persempit utasnya jika masalahnya pada lingkungan multi-utas. Berikan masing-masing utas pengidentifikasi, dan buang saat bug terjadi.
Setelah Anda memiliki utas, taburkan kode utas yang diberikan dengan printfs secara berlebihan untuk memakukan titik di mana ia muncul.
Kemudian telusur balik ke tempat tindakan aktual yang membuatnya terjadi (tindakan destruktif akan sering sedikit sebelum di mana data yang rusak memicu masalah.) Periksa apa struktur / variabel yang terjadi di dekatnya dalam memori, amati loop yang mempengaruhi mereka, periksa poin di mana nilai rusak ditulis untuk.
Setelah Anda memiliki poin yang menyebabkan masalah, sebelum memperbaikinya, pikirkan dua kali perilaku yang benar.