Apa perburuan bug yang paling sulit dan bagaimana Anda menemukannya dan membunuhnya?


31

Ini adalah pertanyaan "Bagikan Pengetahuan". Saya tertarik untuk belajar dari keberhasilan dan / atau kegagalan Anda.

Informasi yang mungkin bermanfaat ...

Latar Belakang:

  • Konteks: Bahasa, Aplikasi, Lingkungan, dll.
  • Bagaimana bug diidentifikasi?
  • Siapa atau apa yang mengidentifikasi bug?
  • Seberapa rumit mereproduksi bug?

Perburuan.

  • Apa rencanamu?
  • Kesulitan apa yang Anda hadapi?
  • Bagaimana kode yang melanggar akhirnya ditemukan?

Pembunuhan.

  • Seberapa rumit perbaikannya?
  • Bagaimana Anda menentukan ruang lingkup perbaikan?
  • Berapa banyak kode yang terlibat dalam perbaikan?

Postmortem.

  • Apa akar penyebabnya secara teknis? buffer overrun, dll.
  • Apa akar penyebabnya dari 30.000 kaki?
  • Berapa lama proses akhirnya berlangsung?
  • Apakah ada fitur yang terpengaruh oleh perbaikan?
  • Metode, alat, dan motivasi apa yang menurut Anda sangat membantu? ... sangat tidak berguna?
  • Jika Anda bisa melakukan semuanya lagi? ............

Contoh-contoh ini bersifat umum, tidak berlaku dalam setiap situasi dan mungkin tidak berguna. Harap bumbui sesuai kebutuhan.

Jawaban:


71

Itu sebenarnya di sub-komponen penampil gambar pihak ke-3 dari aplikasi kita.

Kami menemukan bahwa ada 2-3 dari pengguna aplikasi kami yang sering memiliki komponen penampil gambar melempar pengecualian dan mati dengan mengerikan. Namun, kami memiliki lusinan pengguna lain yang tidak pernah melihat masalah meskipun menggunakan aplikasi untuk tugas yang sama di sebagian besar hari kerja. Juga ada satu pengguna khususnya yang mendapatkannya lebih sering daripada yang lainnya.

Kami mencoba langkah-langkah biasa:

(1) Apakah mereka beralih komputer dengan pengguna lain yang tidak pernah memiliki masalah untuk mengesampingkan komputer / konfigurasi. - Masalahnya mengikuti mereka.

(2) Apakah mereka masuk ke aplikasi dan bekerja sebagai pengguna yang tidak pernah melihat masalah. - Masalahnya MASIH mengikuti mereka.

(3) Minta pengguna melaporkan gambar mana yang mereka lihat dan mengatur uji coba untuk mengulangi melihat gambar itu ribuan kali berturut-turut dengan cepat. Masalahnya tidak muncul dengan sendirinya di harness.

(4) Suruh pengembang duduk bersama pengguna dan menonton mereka sepanjang hari. Mereka melihat kesalahan, tetapi tidak melihat mereka melakukan sesuatu yang luar biasa menyebabkan mereka.

Kami berjuang dengan ini selama berminggu-minggu mencoba untuk mencari tahu apa "Pengguna Kesalahan" memiliki kesamaan yang tidak dimiliki oleh pengguna lain. Saya tidak tahu caranya, tetapi pengembang pada langkah (4) memiliki momen eureka dalam perjalanan untuk bekerja suatu hari yang layak untuk Encyclopedia Brown.

Dia menyadari bahwa semua "Pengguna Kesalahan" adalah kidal, dan mengkonfirmasi fakta ini. Hanya pengguna kidal yang mendapatkan kesalahan, tidak pernah Righties. Tetapi bagaimana mungkin tangan kiri menyebabkan bug?

Kami menyuruhnya duduk dan menonton orang kidal lagi secara khusus memperhatikan apa pun yang mungkin mereka lakukan secara berbeda, dan itulah bagaimana kami menemukannya.

Ternyata bug hanya terjadi jika Anda memindahkan mouse ke kolom paling kanan piksel dalam penampil gambar saat sedang memuat gambar baru (kesalahan melimpah karena vendor memiliki perhitungan 1-off untuk acara mouseover).

Rupanya, sambil menunggu gambar berikutnya dimuat, semua pengguna secara alami menggerakkan tangan mereka (dan juga mouse) ke arah keyboard.

Satu pengguna yang paling sering mendapatkan kesalahan adalah salah satu tipe ADD yang secara kompulsif menggerakkan mouse-nya dengan tidak sabar sambil menunggu halaman berikutnya dimuat, jadi dia menggerakkan mouse ke kanan lebih cepat dan mengenai waktu yang tepat sehingga dia melakukannya ketika peristiwa beban terjadi. Sampai kami mendapat perbaikan dari vendor, kami katakan padanya untuk melepaskan mouse setelah mengklik (dokumen berikutnya) dan tidak menyentuhnya sampai dimuat.

Sejak saat itu dikenal dalam legenda di tim dev sebagai "The Left Handed Bug"


14
Itu adalah hal paling jahat yang pernah saya dengar.
Nathan Taylor

9
Itu membuat seorang pahlawan dari orang yang menyelesaikannya.
JohnFx

2
Wow, sekarang itu serangga!
Penjual Mitchel

3
Great ditemukan! Cerita yang bagus.
Toon Krijthe

11
Seolah kita orang kidal belum cukup diperlakukan seperti warga negara kelas dua. Sekarang kita juga harus dibebani dengan lebih dari sekadar bug perangkat lunak yang adil ... ya ampun, terima kasih! : p
Dan Moulding

11

Ini sudah lama sekali (akhir 1980-an).

Perusahaan tempat saya bekerja menulis paket CAD (dalam FORTRAN) yang dijalankan pada berbagai workstation Unix (HP, Sun, Silcon Graphics, dll.). Kami menggunakan format file kami sendiri untuk menyimpan data dan ketika paket dimulai ruang disk langka sehingga ada banyak pergeseran bit yang digunakan untuk menyimpan beberapa flag di header entitas.

Jenis entitas (garis, busur, teks, dll) dikalikan dengan 4096 (saya pikir) saat disimpan. Selain itu, nilai ini dinegasikan untuk menunjukkan item yang dihapus. Jadi untuk mendapatkan tipe kita punya kode yang bisa:

type = record[1] MOD 4096

Pada setiap mesin kecuali satu ini memberi ± 1 (untuk sebuah garis), ± 2 (untuk sebuah lengkungan) dll dan kami kemudian dapat memeriksa tanda untuk melihat apakah telah dihapus.

Pada satu mesin (HP saya pikir) kami memiliki masalah aneh di mana penanganan barang yang dihapus telah kacau.

Ini terjadi pada hari-hari sebelum IDE dan visual debugger jadi saya harus memasukkan jejak pernyataan dan masuk untuk mencoba dan melacak masalah.

Saya akhirnya menemukan bahwa itu karena sementara setiap produsen lain diimplementasikan MODsehingga -4096 MOD 4096mengakibatkan -1HP mengimplementasikannya secara matematis sehingga -4096 MOD 4096menghasilkan -4097.

Saya akhirnya harus melalui seluruh basis kode menyimpan tanda nilai dan membuatnya positif sebelum melakukan MODdan kemudian mengalikan hasilnya dengan nilai tanda.

Ini memakan waktu beberapa hari.


3
Mungkin ada perburuan bug yang lebih sulit selama bertahun-tahun, tetapi yang ini telah melekat dalam pikiran saya selama lebih dari 20 tahun!
ChrisF

7

Wow, bacaan yang bagus di sini!

Terberat saya adalah tahun-tahun yang lalu ketika Turbo Pascal besar, meskipun itu mungkin salah satu IDE C ++ awal waktu itu. Sebagai pengembang tunggal (dan orang ketiga dalam startup ini) saya telah menulis sesuatu seperti program CAD ramah penjual yang disederhanakan. Itu hebat pada saat itu, tetapi mengembangkan kecelakaan acak yang tidak menyenangkan. Mustahil untuk mereproduksi, tetapi cukup sering terjadi sehingga saya memulai perburuan bug.

Strategi terbaik saya adalah satu langkah dalam debugger. Bug terjadi hanya ketika pengguna telah memasukkan cukup banyak gambar dan mungkin harus dalam mode atau kondisi zoom tertentu, jadi ada banyak pengaturan yang membosankan dan membersihkan breakpoint, berjalan secara normal selama satu menit untuk memasukkan gambar, dan kemudian langkah melalui sejumlah besar kode. Terutama membantu adalah breakpoints yang akan melewati beberapa kali penyesuaian kemudian istirahat. Seluruh latihan ini harus diulang beberapa kali.

Akhirnya saya mempersempitnya ke suatu tempat di mana subroutine dipanggil, diberi 2 tetapi dari dalamnya terlihat beberapa nomor omong kosong. Saya bisa menangkap ini sebelumnya, tetapi belum melangkah ke subrutin ini, dengan asumsi bahwa ia mendapatkan apa yang diberikan. Buta dengan menganggap hal-hal yang paling sederhana baik-baik saja!

Ternyata isian int 16 bit pada stack, tetapi subrutin mengharapkan 32-bit. Atau semacam itu. Kompiler tidak secara otomatis memasukkan semua nilai menjadi 32 bit, atau melakukan pengecekan tipe yang memadai. Itu sepele untuk diperbaiki, hanya sebagian dari satu baris, hampir tidak ada pemikiran yang diperlukan. Tetapi untuk sampai ke sana butuh tiga hari berburu dan mempertanyakan yang sudah jelas.

Jadi saya punya pengalaman pribadi dengan anekdot tentang konsultan mahal yang masuk, setelah beberapa saat membuat satu ketukan di suatu tempat, dan biaya $ 2000. Eksekutif menuntut gangguan, dan $ 1 untuk keran, $ 1999 untuk mengetahui di mana untuk mengetuk. Kecuali dalam kasus saya, sudah waktunya bukan uang.

Pelajaran yang dipetik: 1) menggunakan kompiler terbaik, di mana "terbaik" didefinisikan sebagai termasuk memeriksa sebanyak mungkin masalah yang diketahui oleh ilmu komputer bagaimana memeriksa, dan 2) mempertanyakan hal-hal sederhana yang jelas, atau setidaknya memverifikasi fungsi yang tepat.

Sejak saat itu semua bug yang sulit menjadi sangat sulit, seperti yang saya tahu untuk memeriksa hal-hal sederhana secara lebih menyeluruh daripada yang diperlukan.

Pelajaran 2 juga berlaku untuk bug elektronik terberat yang pernah saya perbaiki, juga dengan perbaikan sepele, tetapi beberapa EE pintar telah buntung selama berbulan-bulan. Tapi ini bukan forum elektronik, jadi saya akan mengatakan tidak lebih dari itu.


Silakan kirim bug elektronik di tempat lain dan tautan di sini!
tgkprog

6

Kondisi ras data jaringan dari neraka

Saya sedang menulis klien jaringan / server (Windows XP / C #) untuk bekerja dengan aplikasi serupa pada workstation yang sangat lama (Encore 32/77) yang ditulis oleh pengembang lain.

Apa yang dilakukan aplikasi pada dasarnya adalah berbagi / memanipulasi data tertentu pada host untuk mengontrol proses host yang menjalankan sistem dengan UI layar sentuh multi-monitor mewah berbasis PC kami.

Itu melakukan ini dengan struktur 3 lapis. Proses komunikasi membaca / menulis data ke / dari host, melakukan semua konversi format yang diperlukan (endianness, format floating point, dll) dan menulis / membaca nilai-nilai ke / dari database. Basis data bertindak sebagai perantara data antara comms dan UI layar sentuh. Aplikasi UI layar sentuh menghasilkan antarmuka layar sentuh berdasarkan berapa banyak monitor yang terpasang pada PC (secara otomatis mendeteksi ini).

Dalam jangka waktu yang diberikan paket nilai antara host dan pc kami hanya bisa mengirim 128 nilai maks melalui kabel pada suatu waktu dengan latensi maksimum ~ 110ms per round trip (UDP digunakan dengan koneksi ethernet x-over langsung antara komputer). Jadi, jumlah variabel yang diizinkan berdasarkan jumlah variabel layar sentuh yang terpasang berada di bawah kendali ketat. Juga, tuan rumah (walaupun memiliki arsitektur multi-prosesor yang cukup kompleks dengan bus memori bersama yang digunakan untuk komputasi waktu nyata) memiliki sekitar 1/100 kekuatan pemrosesan ponsel saya sehingga ditugaskan untuk melakukan pemrosesan sesedikit mungkin dan servernya / klien harus ditulis dalam pertemuan untuk memastikan hal ini (tuan rumah menjalankan simulasi waktu nyata yang tidak dapat dipengaruhi oleh program kami).

Masalahnya adalah. Beberapa nilai, ketika diubah pada layar sentuh tidak akan hanya mengambil nilai yang baru dimasukkan tetapi akan siklus secara acak antara nilai itu dan nilai sebelumnya. Itu dan hanya pada beberapa nilai tertentu pada beberapa halaman tertentu dengan kombinasi halaman tertentu yang pernah menunjukkan gejala. Kami hampir melewatkan masalah sepenuhnya sampai kami mulai menjalankannya melalui proses penerimaan pelanggan awal


Untuk menjelaskan masalah ini, saya memilih salah satu nilai berosilasi:

  • Saya memeriksa aplikasi Touchscreen, itu berosilasi
  • Saya memeriksa database, berosilasi
  • Saya memeriksa aplikasi comms, berosilasi

Kemudian saya pecah wireshark dan mulai secara manual decoding paket menangkap. Hasil:

  • Tidak terombang-ambing tetapi paket tidak terlihat benar, ada terlalu banyak data.

Saya melangkah melalui setiap detail kode komunikasi seratus kali tanpa menemukan cacat / kesalahan.

Akhirnya saya mulai mengirim email ke dev lain yang bertanya secara detail bagaimana akhirnya dia bekerja untuk melihat apakah ada sesuatu yang saya lewatkan. Lalu saya menemukannya.

Rupanya, ketika dia mengirim data dia tidak menyiram array data sebelum pengiriman jadi, pada dasarnya, dia hanya menimpa buffer terakhir yang digunakan dengan nilai-nilai baru menimpa yang lama, tetapi nilai-nilai lama yang tidak ditimpa masih dikirim.

Jadi, jika nilai berada di posisi 80 dari array data dan daftar nilai yang diminta berubah menjadi kurang dari 80 tetapi nilai yang sama terkandung dalam daftar baru, maka kedua nilai akan ada di buffer data untuk buffer spesifik di setiap diberikan waktu.

Nilai yang dibaca dari database tergantung pada irisan waktu ketika UI meminta nilai.


Cara mengatasinya sangat sederhana. Baca dalam jumlah item yang masuk pada buffer data (Itu sebenarnya terkandung sebagai bagian dari protokol paket) dan jangan membaca buffer di luar jumlah item.


Pelajaran yang dipelajari:

  • Jangan anggap daya komputasi modern begitu saja. Ada saat ketika komputer tidak mendukung ethernet dan ketika membilas array dapat dianggap mahal. Jika Anda benar-benar ingin melihat seberapa jauh kami datang, bayangkan sebuah sistem yang hampir tidak memiliki bentuk alokasi memori dinamis. IE, proses eksekutif harus pra-mengalokasikan semua memori untuk semua program agar dan tidak ada program yang dapat tumbuh melampaui batas itu. Yaitu, mengalokasikan lebih banyak memori ke program tanpa mengkompilasi ulang seluruh sistem dapat menyebabkan crash besar. Saya ingin tahu apakah orang akan berbicara tentang hari-hari pengumpulan sampah di hari yang sama suatu hari nanti.

  • Saat melakukan jaringan dengan protokol khusus (atau menangani representasi data biner secara umum), pastikan Anda membaca spesifikasi hingga Anda memahami setiap fungsi dari setiap nilai yang dikirim melintasi pipa. Maksudku, baca sampai matamu sakit. Orang yang menangani data dengan memanipulasi bit atau byte individu memiliki cara yang sangat cerdas dan efisien dalam melakukan sesuatu. Kehilangan detail terkecil dapat merusak sistem.

Waktu keseluruhan untuk memperbaikinya adalah 2-3 hari dengan sebagian besar waktu itu dihabiskan untuk mengerjakan hal-hal lain ketika saya merasa frustrasi dengan ini.

SideNote: Komputer host yang dimaksud tidak mendukung ethernet secara default. Kartu untuk dikendarai dibuat khusus dan dipasang kembali dan tumpukan protokol hampir tidak ada. Pengembang tempat saya bekerja adalah seorang programmer yang hebat, dia tidak hanya mengimplementasikan versi UDP yang dipreteli dan tumpukan ethernet palsu mimimal (prosesor tidak cukup kuat untuk menangani tumpukan ethernet penuh) pada sistem untuk proyek ini. tapi dia melakukannya dalam waktu kurang dari seminggu. Dia juga menjadi salah satu pemimpin tim proyek asli yang telah merancang dan memprogram OS di tempat pertama. Katakan saja, apa saja yang pernah dia bagikan tentang komputer / pemrograman / arsitektur tidak peduli berapa lama atau berapa banyak saya sudah baru, saya akan mendengarkan setiap kata.


5

Latar belakang

  • Dalam sebuah aplikasi misi kritis WCF mengendarai sebuah situs web dan menyediakan pemrosesan trasiaksi backend ..
  • Aplikasi Volume Besar (ratusan panggilan per detik)
  • Beberapa server beberapa contoh
  • ratusan unit test yang lulus dan serangan QA yang tak terhitung jumlahnya

Serangga

  • Ketika dipindahkan ke produksi server akan berjalan dengan baik untuk jumlah waktu acak kemudian mulai dengan cepat menurunkan dan membawa CPU kotak ke 100%.

Bagaimana saya menemukannya

Pada awalnya saya yakin ini adalah masalah kinerja normal jadi saya membuat logging yang rumit. Memeriksa kinerja pada setiap panggilan, berbicara dengan orang-orang di pangkalan data tentang pemanfaatan, mengawasi server untuk masalah. 1 minggu

Kemudian saya yakin saya memiliki masalah pertentangan topik. Saya memeriksa kebuntuan saya mencoba membuat situasi, membuat alat untuk mencoba membuat situasi dalam debug. Dengan frustrasi manajemen yang meningkat, saya menoleh ke rekan-rekan saya bagaimana menyarankan hal-hal dari memulai kembali proyek dari awal hingga membatasi server ke satu utas. 1,5 minggu

Kemudian saya melihat blog Tess Ferrandez membuat file dump pengguna dan menganalasinya dengan windebug saat server mengambil dump. Menemukan bahwa semua utas saya tersangkut di fungsi dictionary.add.

Panjang satu kamus kecil pendek yang hanya melacak yang log untuk menulis kesalahan x utas untuk tidak disinkronkan.


3

Kami memiliki aplikasi yang sedang berbicara dengan perangkat perangkat keras yang, dalam beberapa kasus, akan gagal beroperasi dengan benar jika perangkat dicabut secara fisik hingga terpasang kembali dan soft-reset dua kali.

Masalahnya ternyata adalah aplikasi yang berjalan saat startup kadang-kadang melakukan segmentasi ketika mencoba membaca dari sistem file yang belum di-mount (misalnya, jika pengguna mengkonfigurasinya untuk membaca dari volume NFS). Saat memulai aplikasi akan mengirim beberapa ioctls ke driver untuk menginisialisasi perangkat, kemudian membaca pengaturan konfigurasi dan mengirim lebih banyak ioctl untuk menempatkan perangkat dalam keadaan yang benar.

Bug dalam driver menyebabkan nilai yang tidak valid untuk ditulis ke perangkat ketika panggilan inisialisasi dibuat, tetapi nilai tersebut ditimpa dengan data yang valid setelah panggilan dilakukan untuk menempatkan perangkat dalam keadaan tertentu.

Perangkat itu sendiri memiliki baterai dan akan mendeteksi jika kehilangan daya dari motherboard, dan akan menulis bendera ke memori volatil yang menunjukkan bahwa ia telah kehilangan daya, maka ia akan memasuki keadaan tertentu saat berikutnya dihidupkan, dan spesifik instruksi harus dikirim untuk menghapus bendera.

Masalahnya adalah jika daya dihilangkan setelah ioctl dikirim untuk menginisialisasi perangkat (dan menulis nilai yang tidak valid ke perangkat) tetapi sebelum data yang valid dapat dikirim. Ketika perangkat dinyalakan kembali, itu akan melihat bendera telah ditetapkan dan mencoba untuk membaca data yang tidak valid yang telah dikirim dari driver karena inisialisasi yang tidak lengkap. Ini akan membuat perangkat dalam keadaan tidak valid di mana bendera dimatikan telah dihapus tetapi perangkat tidak akan menerima instruksi lebih lanjut sampai telah diinisialisasi ulang oleh pengemudi. Reset kedua akan berarti bahwa perangkat tidak mencoba membaca data yang tidak valid yang telah disimpan di dalamnya, dan akan menerima instruksi konfigurasi yang benar, yang memungkinkannya untuk dimasukkan ke keadaan yang benar (dengan asumsi aplikasi yang mengirim ioctl tidak segfault ).

Pada akhirnya butuh sekitar dua minggu untuk mencari tahu keadaan yang menyebabkan masalah itu.


2

Untuk proyek Universitas kami sedang menulis sistem P2P Nodes Terdistribusi yang berbagi file, ini mendukung multicasting untuk mendeteksi satu sama lain, beberapa cincin node dan server nama sehingga sebuah node ditugaskan ke klien.

Ditulis dalam C ++ kami menggunakan POCO untuk ini karena memungkinkan pemrograman IO, Socket dan Thread yang bagus.


Ada dua bug yang muncul yang mengganggu kami dan membuat kami kehilangan banyak waktu, yang benar-benar logis:

Secara acak, komputer membagikan IP localhost-nya, bukan IP jarak jauh.

Hal ini menyebabkan klien terhubung ke node pada PC atau node yang sama untuk terhubung dengan diri mereka sendiri.

Bagaimana kami mengidentifikasi ini? Ketika kami meningkatkan output di server nama yang kami temukan di saat kemudian ketika kami mem-boot ulang komputer yang oleh skrip kami untuk menentukan IP yang diberikan adalah salah. Secara acak, perangkat lo terdaftar lebih dulu daripada perangkat eth0 ... Benar-benar bodoh. Jadi sekarang kami hardcoded untuk meminta kembali dari eth0 karena ini dibagikan di antara semua komputer universitas ...


Dan sekarang yang lebih menyebalkan:

Secara acak, aliran paket akan berhenti secara acak.
Ketika klien berikutnya terhubung, ia akan melanjutkan ...

Ini terjadi benar-benar acak dan karena lebih dari satu komputer terlibat maka semakin menjengkelkan untuk men-debug masalah ini, komputer universitas tidak memungkinkan kita untuk menjalankan Wireshark pada mereka sehingga kita dibiarkan menebak apakah masalahnya ada di sisi pengirim atau penerima sisi.

Dengan banyak output dalam kode kami hanya mengambil asumsi bahwa mengirim perintah berjalan dengan baik,
ini membuat kami bertanya-tanya di mana masalah sebenarnya adalah ... Tampaknya cara pemilihan POCO salah dan bahwa kami harus memeriksa karakter yang tersedia pada soket yang masuk.

Kami mengambil asumsi bahwa ini berfungsi sebagai tes yang lebih sederhana dalam prototipe yang melibatkan lebih sedikit paket tidak menyebabkan masalah ini, jadi ini menyebabkan kami hanya berasumsi bahwa pernyataan polling berfungsi tetapi ... Tidak. :-(


Pelajaran yang dipelajari:

  • Jangan membuat asumsi bodoh seperti urutan perangkat jaringan.

  • Kerangka kerja tidak selalu melakukan tugasnya (baik implementasi atau dokumentasi) dengan benar.

  • Berikan output yang cukup dalam kode, jika tidak diizinkan pastikan untuk mencatat detail yang diperluas ke file.

  • Ketika kode belum diuji unit (karena terlalu sulit) jangan menganggap hal-hal berfungsi.


1
Mengatasi masalah jaringan tanpa wireshark (atau alat serupa) adalah heroik di / dari iteslf.
Evan Plaice

2

Saya masih mencari bug yang paling sulit. Itu salah satu dari mereka yang terkadang ada di sana dan kadang-kadang itu bukan bug. Itulah sebabnya saya di sini, pada jam 6:10 pagi hari berikutnya.

Latar Belakang:

  • Konteks: Bahasa, Aplikasi, Lingkungan, dll.
    • PHP OS Commerce
  • Bagaimana bug diidentifikasi?
    • Urutan acak yang berfungsi sebagai bagian dari masalah gagal dan redirect secara acak
  • Siapa atau apa yang mengidentifikasi bug?
    • Klien, dan masalah pengalihan jelas
  • Seberapa rumit mereproduksi bug?
    • Saya belum bisa mereproduksi, tetapi klien sudah bisa.

Perburuan.

  • Apa rencanamu?
    • Tambahkan kode debug, isi pesanan, analisis data, ulangi
  • Kesulitan apa yang Anda hadapi?
    • Kurangnya masalah berulang dan kode mengerikan
  • Bagaimana kode yang melanggar akhirnya ditemukan?
    • banyak kode menyinggung ditemukan .. hanya tidak persis apa yang saya butuhkan.

Pembunuhan.

  • Seberapa rumit perbaikannya?
    • sangat
  • Bagaimana Anda menentukan ruang lingkup perbaikan?
    • tidak ada ruang lingkup ... itu ada di mana-mana
  • Berapa banyak kode yang terlibat dalam perbaikan?
    • Semua itu? Saya tidak berpikir ada file yang tidak tersentuh

Postmortem.

  • Apa akar penyebabnya secara teknis? buffer overrun, dll.
    • praktik pengkodean yang buruk
  • Apa akar penyebabnya dari 30.000 kaki?
    • Saya lebih suka tidak mengatakan ...
  • Berapa lama proses akhirnya berlangsung?
    • Sehari dan selamanya
  • Apakah ada fitur yang terpengaruh oleh perbaikan?
    • fitur? atau itu bug?
  • Metode, alat, dan motivasi apa yang menurut Anda sangat membantu? ... sangat tidak berguna?
  • Jika Anda bisa melakukan semuanya lagi? ............
    • ctrl + a Del

Jika alasannya adalah "praktik pengkodean yang buruk", Anda mungkin ingin berdiskusi dengan atasan Anda apakah ini saat yang tepat untuk merevisi praktik pengkodean tim Anda, dan mungkin memperkenalkan peer review?

2

Saya harus memperbaiki beberapa soal konkurensi semseter terakhir yang membingungkan, tetapi bug yang paling menonjol bagi saya adalah dalam permainan berbasis teks yang saya tulis di majelis PDP-11 untuk tugas pekerjaan rumah. Itu didasarkan pada Permainan Kehidupan Conway dan untuk beberapa alasan aneh sebagian besar informasi di sebelah grid terus-menerus ditimpa dengan informasi yang seharusnya tidak ada di sana. Logikanya juga cukup mudah, jadi sangat membingungkan. Setelah membahasnya beberapa kali untuk menemukan kembali bahwa semua logikanya benar, saya tiba-tiba menyadari apa masalahnya. Hal ini:.

Dalam PDP-11 titik kecil ini di samping angka menjadikannya basis 10 bukan 8. Itu di sebelah angka yang membatasi loop yang seharusnya terbatas pada kisi, yang ukurannya didefinisikan dengan angka yang sama tetapi dalam basis 8.

Itu masih menonjol bagi saya karena jumlah kerusakan yang disebabkan oleh penambahan berukuran 4 pixel yang sangat kecil. Jadi apa kesimpulannya? Jangan kode dalam perakitan PDP-11.


2

Program Main-Frame Berhenti Berfungsi Tanpa Alasan

Saya hanya memposting ini ke pertanyaan lain. Lihat Posting di Sini

Itu terjadi karena mereka menginstal versi kompiler yang lebih baru pada Main-Frame.

Pembaruan 06/11/13: (Jawaban asli dihapus oleh OP)

Saya mewarisi aplikasi bingkai utama ini. Suatu hari, tiba-tiba ia berhenti bekerja. Itu saja ... puf itu baru saja berhenti.

Pekerjaan saya adalah membuatnya bekerja secepat mungkin. Kode sumber belum dimodifikasi selama dua tahun, tetapi tiba-tiba saja berhenti. Saya mencoba untuk mengkompilasi kode dan rusak di baris XX Saya melihat garis XX dan saya tidak tahu apa yang membuat garis XX putus. Saya meminta spesifikasi terperinci untuk aplikasi ini dan tidak ada. Jalur XX bukan pelakunya.

Saya mencetak kode dan mulai memeriksanya dari atas ke bawah. Saya mulai membuat diagram alur dari apa yang sedang terjadi. Kode itu sangat berbelit-belit sampai saya bahkan tidak bisa memahaminya. Saya menyerah mencoba untuk flowchart itu. Saya takut untuk membuat perubahan tanpa mengetahui bagaimana perubahan itu akan mempengaruhi sisa proses, terutama karena saya tidak punya rincian tentang apa yang dilakukan aplikasi.

Jadi, saya memutuskan untuk mulai di bagian atas kode sumber dan menambahkan whitespce dan rem baris untuk membuat kode lebih mudah dibaca. Saya perhatikan, dalam beberapa kasus, ada jika kondisi yang menggabungkan AND dan OR dan tidak jelas dibedakan antara data apa yang sedang ANDed dan data apa yang sedang ORed. Jadi saya mulai menempatkan tanda kurung di sekitar kondisi AND dan OR untuk membuatnya lebih mudah dibaca.

Saat saya perlahan-lahan membersihkannya, saya secara berkala akan menyelamatkan pekerjaan saya. Pada satu titik saya mencoba mengkompilasi kode dan hal aneh terjadi. Kesalahan telah melompat melewati baris kode asli dan sekarang lebih jauh ke bawah. Jadi saya melanjutkan, menjelaskan kondisi AND dan OR dengan orangtua. Ketika saya selesai membersihkannya, itu berhasil. Go Figure.

Saya kemudian memutuskan untuk mengunjungi toko operasi dan bertanya apakah mereka baru saja memasang komponen baru pada kerangka-utama. Mereka berkata ya, kami baru saja meningkatkan kompiler. Hmmmm.

Ternyata kompiler lama mengevaluasi ekspresi dari kiri ke kanan. Versi baru dari kompiler juga mengevaluasi ekspresi dari kiri ke kanan tetapi kode ambigu yang berarti kombinasi AND dan OR yang tidak jelas tidak dapat diselesaikan.

Pelajaran yang saya pelajari dari ini ... SELALU, SELALU, SELALU menggunakan orangtua untuk memisahkan DAN kondisi dan ATAU kondisi ketika mereka digunakan bersama satu sama lain.


pos tautan yang Anda tuju telah dihapus - maukah Anda memperbarui jawabannya?
nyamuk

1
@gnat - Ditemukan di archive.org :)
Michael Riley - AKA Gunny

1

Latar Belakang:

  • Konteks: Server Web (C ++) yang memungkinkan pelanggan untuk check-in sendiri
  • Bug: Ketika meminta halaman, itu tidak akan merespons, seluruh peternakan yang ada, dan prosesnya akan terbunuh (dan diluncurkan kembali) karena terlalu lama (hanya beberapa detik diizinkan) untuk melayani halaman
  • Beberapa pengguna memang mengeluh, tetapi itu sangat sporadis sehingga sebagian besar tidak diketahui (orang-orang cenderung menekan "Refresh" ketika halaman tidak disajikan). Kami memang memperhatikan core dumps;)
  • Kami sebenarnya tidak pernah berhasil mereproduksi di lingkungan lokal kami, bug muncul beberapa kali dalam sistem Uji tetapi tidak pernah muncul selama Tes Kinerja ??

Perburuan.

  • Paket: Ya, karena kami memiliki memori dump dan log, kami ingin menganalisisnya. Karena itu memengaruhi seluruh tambak dan kami memiliki beberapa masalah basis data di masa lalu, kami mencurigai basis data (DB tunggal untuk beberapa server)
  • Kesulitan: Dump server lengkap sangat besar, sehingga mereka cukup sering dibersihkan (tidak kehabisan ruang), jadi kami harus cepat mengambilnya ketika itu terjadi ... Kami bertahan. Tumpukan menunjukkan berbagai tumpukan (tidak pernah ada barang DB, begitu banyak untuk itu), gagal saat menyiapkan halaman itu sendiri (tidak dalam perhitungan sebelumnya), dan mengkonfirmasi apa yang ditunjukkan oleh log, menyiapkan halaman terkadang membutuhkan waktu lama, bahkan meskipun itu hanya mesin templat dasar dengan data pra-komputasi (MVC tradisional)
  • Cara mendapatkannya: Setelah beberapa sampel lagi dan beberapa pemikiran kami menyadari bahwa waktu diambil membaca data dari HDD (templat halaman). Karena ini menyangkut seluruh peternakan, kami pertama kali mencari pekerjaan yang dijadwalkan (crontab, batch) tetapi timing tidak pernah cocok dari satu kejadian ke yang lain ... Akhirnya saya sadar bahwa ini selalu terjadi beberapa hari sebelum aktivasi versi baru perangkat lunak dan saya punya AhAh! saat ... itu disebabkan oleh distribusi perangkat lunak! Memberikan beberapa ratus megabyte (terkompresi) dapat mengurangi kinerja disk: / Tentu saja distribusinya otomatis dan arsip didorong ke semua server sekaligus (multicast).

Pembunuhan.

  • Perbaiki Kompleksitas: beralih ke templat yang dikompilasi
  • Kode yang Terkena Dampak: tidak ada, perubahan sederhana dalam proses pembuatan

Postmortem.

  • Penyebab root: masalah operasional atau kurangnya perencanaan ke depan :)
  • Timescale: butuh berbulan-bulan untuk dilacak, hitungan hari untuk memperbaikinya dan menguji, beberapa minggu untuk QA dan pengujian dan penyebaran Kinerja - tidak terburu-buru di sana, karena kami tahu bahwa menyebarkan perbaikan akan memicu bug ... dan tidak ada lain ... agak cabul kok!
  • Efek samping yang merugikan: ketidakmungkinan untuk mengganti template saat runtime sekarang karena mereka dipanggang dalam kode yang dikirimkan, meskipun kami tidak menggunakan banyak fitur, karena umumnya beralih template berarti bahwa Anda memiliki lebih banyak data untuk dituangkan. Menggunakan css adalah sebagian besar cukup untuk perubahan tata letak "kecil".
  • Metode, alat: gdb+ pemantauan! Hanya perlu waktu bagi kami untuk mencurigai disk tersebut, dan kemudian mengidentifikasi penyebab lonjakan aktivitas pada grafik pemantauan ...
  • Lain kali: perlakukan semua IO sebagai merugikan!

1

Yang paling sulit tidak pernah terbunuh karena tidak pernah bisa diperbanyak selain di lingkungan produksi penuh dengan pabrik yang beroperasi.

Yang paling gila yang saya bunuh:

Gambar-gambarnya sedang dicetak omong kosong!

Saya melihat kode dan saya tidak bisa melihat apa pun. Saya menarik pekerjaan dari antrian printer dan memeriksanya, itu terlihat baik-baik saja. (Ini di era dos, PCL5 dengan HPGl / 2 tertanam - sebenarnya, sangat bagus untuk memplot gambar dan tidak sakit kepala membangun gambar raster dalam memori terbatas.) Saya mengarahkannya ke printer lain yang harus memahaminya, ia mencetak dengan baik .

Putar kembali kodenya, masalahnya masih ada.

Akhirnya saya secara manual membuat file sederhana dan mengirimkannya ke printer - omong kosong. Ternyata itu bukan bug saya sama sekali tetapi printer itu sendiri. Perusahaan pemeliharaan telah menginstalnya ke versi terbaru ketika mereka memperbaiki sesuatu yang lain dan versi terbaru memiliki bug. Membuat mereka mengerti bahwa mereka telah mengambil fungsionalitas kritis dan harus mem-flash-nya kembali ke versi sebelumnya lebih sulit daripada menemukan bug itu sendiri.

Satu yang bahkan lebih menjengkelkan tetapi karena hanya ada di kotak saya, saya tidak akan menempatkan di tempat pertama:

Borland Pascal, kode DPMI untuk menangani beberapa API yang tidak didukung. Jalankan, sesekali berhasil, biasanya booming mencoba berurusan dengan pointer yang tidak valid. Itu tidak pernah menghasilkan hasil yang salah, seperti yang Anda harapkan dari menginjak pointer.

Debug - jika saya melangkah melalui kode itu akan selalu berfungsi dengan benar, kalau tidak itu sama tidak stabilnya seperti sebelumnya. Inspeksi selalu menunjukkan nilai yang benar.

Pelakunya: Ada dua.

1) Kode perpustakaan Borland memiliki bug utama: Pointer mode nyata disimpan dalam variabel pointer dalam mode terproteksi. Masalahnya adalah bahwa kebanyakan pointer mode nyata memiliki alamat segmen yang tidak valid dalam mode terproteksi dan ketika Anda mencoba untuk menyalin pointer itu memuatnya ke dalam pasangan register dan kemudian menyimpannya.

2) debugger tidak akan pernah mengatakan apa pun tentang beban yang tidak valid dalam mode langkah tunggal. Saya tidak tahu apa yang ia lakukan secara internal tetapi apa yang disajikan kepada pengguna tampak sepenuhnya benar. Saya menduga itu tidak benar-benar menjalankan instruksi tetapi mensimulasikannya sebagai gantinya.


1

Ini hanya bug yang sangat sederhana yang entah bagaimana saya berubah menjadi mimpi buruk bagi saya.

Latar Belakang: Saya sedang mengerjakan pembuatan Sistem Operasi saya sendiri. Debugging itu sangat sulit (hanya bisa melacak pernyataan, dan terkadang bahkan tidak)

Bug: Alih-alih melakukan dua sakelar ulir di usermode, ini malah akan menjadi kesalahan perlindungan umum.

Perburuan bug: Saya menghabiskan mungkin satu atau dua minggu mencoba untuk memperbaiki masalah ini. Memasukkan jejak pernyataan di mana-mana. Memeriksa kode assembly yang dihasilkan (dari GCC). Mencetak setiap nilai yang saya bisa.

Masalahnya: Di suatu tempat di awal perburuan bug, saya telah menempatkan hltinstruksi di crt0. Crt0 pada dasarnya adalah bootstrap program pengguna untuk digunakan dalam sistem operasi. hltInstruksi ini menyebabkan GPF ketika dijalankan dari mode pengguna. Saya meletakkannya di sana dan pada dasarnya lupa. (awalnya masalahnya adalah sesuatu dari buffer overflow atau kesalahan alokasi memori)

Cara mengatasinya: Hapus hltinstruksi :) Setelah menghapusnya, semuanya bekerja dengan lancar.

Apa yang saya pelajari: Ketika mencoba men-debug masalah, jangan lupa perbaikan yang Anda coba. Lakukan perbedaan reguler terhadap versi kontrol sumber stabil terbaru dan lihat apa yang telah Anda ubah baru-baru ini ketika tidak ada yang lain yang berfungsi

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.