Bagaimana mereka men-debug kesalahan segmentasi sebelum memori yang dilindungi?

20

Sekarang, ketika saya membuat kesalahan pemrograman dengan pointer di C, saya mendapatkan kesalahan segmentasi yang bagus, program saya macet dan debugger bahkan bisa memberi tahu saya di mana kesalahannya.

Bagaimana mereka melakukan itu di saat perlindungan memori tidak tersedia? Saya bisa melihat seorang programmer DOS mengotak-atik dan menabrak seluruh OS ketika dia melakukan kesalahan. Virtualisasi tidak tersedia, jadi yang bisa ia lakukan hanyalah memulai kembali dan mencoba lagi. Apakah benar-benar seperti itu?

Bart Friederichs
sumber
4
Yap, begitulah caranya. Reboot komputer acak terjadi, dan sering terjadi. Perlindungan memori adalah hal yang luar biasa :)
Rocklan
7
Ketika Anda tidak memiliki memori yang dilindungi, tidak ada kesalahan segmentasi. Tentu saja, bahkan jika Anda memiliki memori yang diproteksi, Anda masih dapat merusak ruang Anda sendiri; OS tidak peduli tentang itu.
Blrfl
3
Bahkan sekarang banyak kesalahan pointer tidak menyebabkan segfault yang bagus.
CodesInChaos
1
Pada saat DOS, memori yang dilindungi sudah ada di OS lain.
mouviciel

Jawaban:

36

Saya bisa melihat seorang programmer DOS mengotak-atik dan menabrak seluruh OS ketika dia melakukan kesalahan.

Ya, itulah yang terjadi. Pada sebagian besar sistem yang memiliki peta memori, lokasi 0 ditandai tidak valid, sehingga pointer nol dapat dengan mudah dideteksi, karena itu adalah kasus yang paling umum. Tetapi ada banyak kasus lain, dan mereka menyebabkan kekacauan.

Dengan risiko terdengar seperti kakek tua, saya harus menunjukkan bahwa fokus saat ini pada debugging bukan cara masa lalu. Banyak upaya yang dilakukan sebelumnya untuk menulis program yang benar, daripada menghapus bug dari program yang salah. Beberapa di antaranya adalah karena itu adalah tujuan kami, tetapi banyak karena alat membuat segalanya menjadi sulit. Cobalah menulis program Anda di atas kertas atau kartu yang dilubangi, bukan dalam IDE, dan tanpa manfaat dari debugger interaktif. Ini memberi Anda rasa untuk kebenaran.

Ross Patterson
sumber
3
Bahkan, saya berharap "kakek tua" akan menjawab pertanyaan saya. Tidak ada yang mengalahkan pengalaman tangan pertama. Terima kasih.
Bart Friederichs
6
Cobalah menulis kode ketika perangkat keras tersedia untuk debugging setiap malam mulai pukul 02:00 hingga 06:00, dengan asumsi tentu saja kolega Anda tidak mencadangkannya untuk sesi debugnya.
MSalters
@Malters Memang! Pada pekerjaan pertama saya, kami juga bisa memesan slot pada hari Minggu dari 0700 hingga 1900 - benar-benar menyenangkan, biar saya beri tahu :-)
Ross Patterson
2
Saya ingat menulis program pertama saya di atas kertas yang pulang dari universitas. Hari berikutnya ketika saya bisa memencetnya dan menjalankannya, itu sempurna ;-)
Jan Doggen
1
@JanDoggen, sama untuk saya. Ketika Anda hanya memiliki satu percobaan Anda membuat percobaan itu benar-benar diperhitungkan.
nalply
23

Kembali di hari saya, kami tidak memiliki perlindungan memori dan semua bisnis yang manis! Kami menggunakan printf untuk menentukan di mana kami berada dalam program ini, dan kami menyukainya !

Meskipun dengan serius, biasanya itu berarti kami hanya lebih berhati-hati. Di mana malloc dipanggil, harus ada tempat lain yang bebas dalam program, dan pengecekan seperti itu sangat ketat karena dalam kasus masalah, seperti yang telah Anda jelaskan, kesalahan segmentasi bukanlah kesalahan yang membantu.

Dalam hal kesalahan seperti itu, yang terbaik yang bisa Anda lakukan adalah mencoba memahami ketika kesalahan segmentasi tersebut terjadi (menggunakan printf) dan, melihat kode, menentukan mengapa akses ke memori pada saat itu tidak valid dan bekerja mundur dari sana.

Pada dasarnya, hal yang sama terjadi hari ini, kecuali kami menggunakan debugger untuk menentukan kapan kesalahan terjadi, tetapi Anda masih harus memahami mengapa itu terjadi, dan itu tidak selalu sesederhana menemukan garis di mana kesalahan terjadi. Kesalahan menyebabkan kesalahan seperti reaksi berantai, dan jika Anda adalah seorang programmer C pada masa itu, Anda menghabiskan 20% dari waktu Anda mengkodekan dan sisanya menarik rambut Anda untuk memperbaiki bug.

Neil
sumber
2
Bebaskan Mallocs!
Chris
1
Sekali-sekali, bahkan hari ini, bahkan tumpukan panggilan dan keadaan variabel sama sekali tidak berguna untuk menentukan apa yang salah dan bagaimana cara memperbaikinya. Itu terjadi terutama jika Anda memiliki perangkat lunak yang kompleks dengan sejumlah besar kemungkinan keadaan, beberapa di antaranya saling tergantung dan beberapa saling eksklusif. Satu tulisan nyasar di mana saja dan pernyataan yang dihilangkan untuk prasyarat yang dijamin dapat membawa Anda ke sana.
CVn
1
@ MichaelKjörling, saya pikir untuk masalah menemukan kesalahan dalam program, kami telah berkembang hanya untuk masalah apa yang menemukan pemicu kesalahan, tetapi kami masih harus mencari cara untuk mengungkap penyebab kesalahan ini. Pernyataan membantu membuat saya tetap waras, pasti. :)
Neil
6

yah ..

segfault adalah indikator yang sangat bagus bahwa ada sesuatu yang salah tetapi Anda masih harus menemukan akar masalahnya. Jadi, jika Anda mengajukan pertanyaan bagaimana Anda menemukan akar penyebab daripada jawabannya tidak jauh berbeda hari ini daripada sebelumnya. Tentu saja bahasa dan alat menjadi lebih mudah untuk dikerjakan tetapi motivasi umumnya sama:

  • logging membantu menemukan area tempat masalah Anda. Printf biner adalah bentuknya.
  • debugging, langkah demi langkah, break point dan jam tangan
  • refactoring untuk mendapatkan pemahaman yang lebih baik
  • menatap keras ke kode
  • lihat memori / dump inti
  • memberinya makan dengan data yang berbeda
  • menunjukkannya kepada orang lain
  • beralih ke bahasa tanpa petunjuk (dan satu set masalah baru) ...

Pada tingkat yang lebih abstrak, Anda memiliki tiga pendekatan: 1. bekerja dengan kode 2. melihat program saat berjalan 3. melihat hasilnya setelah melakukan sesuatu yang bodoh

btw kesalahan pointer tidak harus membuat segfault.

Sebagai seorang programmer Amiga saya menggunakan hampir semuanya. Dan ya memulai kembali di mana praktik umum.

openCage
sumber
4

Di IBM 360, menjalankan pekerjaan batch Fortran, kami biasa mendapatkan dump hex core. Tumpukan seperti itu bisa setebal satu inci tebal kertas printer hijau-putih lipat-kipas. Itu akan memberitahu apa register itu, dan dari sana kita bisa mundur dan mencari tahu apa yang sedang dilakukan program. Kami dapat menemukan setiap subrutin dan mencari tahu di mana ia menyimpan alamat pengirimnya, sehingga kami dapat melihat konteksnya. Ini akan membantu untuk memiliki daftar assembler program.

Mike Dunlavey
sumber
2

Suatu hari saya sedang mengerjakan perbaikan bug pada perangkat lunak Presentasi Windows 3.1 yang terkenal saat itu.

Saya memiliki bug yang, ketika itu terjadi, menyebabkan Blue Screen of Death.

Bug hanya terjadi ketika loop tertentu telah dieksekusi lebih dari 1000 kali. Saya menggunakan fitur-fitur canggih dari debugger untuk membiarkan break point melewati 1000 kali dan kemudian saya hati-hati melangkah melalui program. Setiap kali saya melangkah terlalu jauh atau melewatkan panggilan fungsi yang mengandung bug Windows Blue Screened.

Akhirnya, setelah beberapa hari bekerja, saya mempersempitnya ke fungsi yang kehabisan memori dan alih-alih menampilkan pesan kesalahan, menambahkan pesan kesalahan ke buffer. Dengan setiap iterasi berikutnya, ia menghancurkan lebih banyak memori hingga sesuatu yang penting ditimpa dan Windows dihancurkan.

Keterampilan debugging dan ketekunan adalah solusinya.

Stuart Woodward
sumber