Bisakah "bug level 256" dalam game Pacman dianggap sebagai segfault yang tidak ditangani?


51

Saya mencoba menjelaskan kesalahan segmentasi kepada seseorang, dan saya berpikir tentang tingkat 256 kill-screen di Pacman, dan bagaimana hal itu dipicu oleh integer overflow, dan seberapa mirip perilakunya dengan "keadaan tidak dikenal" yang sering dijelaskan dalam segmentasi kesalahan.

Saya ingin mengatakan ini adalah contoh yang baik dari apa yang saya sebut "segfault tidak tertangani", tetapi saya lebih suka mendapatkan pendapat kedua sebelum saya berpotensi menyebarkan informasi yang salah.

Saya mencoba mencarinya, tetapi yang saya dapatkan hanyalah dokumen tentang bug itu sendiri, serta perselisihan antara Paus Hipster dan Namco.

Jadi, apakah Anda menganggap perilaku di tingkat 256 Pacman sebagai contoh pelanggaran segmentasi yang tidak ditangani?


3
Berikut adalah deskripsi bug yang tepat, beserta tambalan untuk memperbaikinya: donhodges.com/how_high_can_you_get2.htm
abligh

26
Kesalahan segmentasi dimunculkan oleh perangkat keras, untuk menghindari akses memori ilegal. Saya bukan ahli Pacman, tetapi perangkat keras yang dijalankannya hampir pasti tidak memiliki fitur keselamatan ini.
BlueRaja - Danny Pflughoeft

3
Menurut wikipedia Pacman menggunakan Z80. Z80s jelas tidak memiliki perlindungan memori.
Gort the Robot

Ini bukan segfault — sistem tidak memiliki bentuk perlindungan memori apa pun. Kesalahan yang dialami Pac-Man pada level 256 hanyalah sebuah integer overflow yang tidak ditangani dengan benar oleh kode gim.
bwDraco

3
FYI, saya rasa ini tidak memenuhi syarat sebagai bug. Bug adalah kegagalan atau kesalahan dalam program atau sistem komputer yang menyebabkannya menghasilkan hasil yang salah atau tidak terduga, atau berperilaku dengan cara yang tidak disengaja. Itu sengaja diprogram seperti itu, karena dirasakan bahwa tidak ada yang akan sampai ke tingkat itu. Pada kenyataannya, desain perangkat lunaknya buruk.
Keltari

Jawaban:


113

Tentu saja tidak.

Mengakses alamat memori yang tidak Anda alokasikan selalu merupakan kesalahan pemrograman. Dan bertindak berdasarkan informasi yang Anda dapatkan darinya menghasilkan perilaku yang tidak terdefinisi, sebanyak itu akurat. Saya tidak tahu platform apa yang ditulis Pac-man asli, tapi saya cukup yakin itu menunjukkan perilaku ini sama seperti mesin von Neumann lainnya.

Namun, "kesalahan segmentasi" adalah istilah teknis untuk kondisi yang jauh lebih spesifik. Itu terjadi ketika komputer secara otomatis mendeteksi bahwa ini terjadi dan menghentikan proses daripada membiarkan perilaku yang tidak ditentukan terjadi. Ini membutuhkan model memori khusus (tersegmentasi) dengan penandaan kepemilikan yang canggih. Saya tidak berpikir 1980 permainan arcade memiliki itu, dan sebenarnya perilaku permainan menunjukkan bahwa kesalahan itu tidak terdeteksi, dan perilaku yang tidak terdefinisi memang terjadi.


19
@ B1KMusic: Anda benar - benar bertanya "apakah kode ini 'bug' contoh memohon perilaku tidak terdefinisi melalui akses memori di luar batas", dan jawabannya adalah "ya". Setiap rasionalisasi tentang menangkap, mengabaikan, tidak mendapatkan sinyal SIGSEGV hanyalah masalah yang membingungkan.
Lightness Races dengan Monica

5
@ B1KMusic tidak semua buffer overruns menghasilkan segfault. Itu tergantung pada bagaimana memori dialokasikan. Jika memori dialokasikan secara statis (satu buffer besar dibagi secara manual di zona yang berbeda) dan area tepat di belakang level terakhir digunakan untuk sesuatu (seperti grafik sprite) maka tidak akan segfault.
ratchet freak

6
Sistem arcade lama itu menggunakan OS primitif yang memberi permainan kendali penuh atas perangkat keras, mirip dengan versi awal DOS. Gagasan segfault dalam tipe arsitektur itu adalah non-starter, karena mengasumsikan proses satu berjalan (Pac-Man) tidak memiliki semua memori. Untuk informasi lebih lanjut, orang dapat membaca tentang proyek MAME dan riwayatnya.

20
Perilaku tidak terdefinisi bukan properti dari mesin von Neumann, itu adalah properti dari C, bahasa pemrograman. Program yang ditulis dalam bahasa assembly tidak dapat menunjukkan perilaku yang tidak terdefinisi, karena perilaku instruksi bahasa assembly selalu didefinisikan dengan baik (bahkan jika hasilnya kadang-kadang tidak ditentukan).
Dietrich Epp

8
@Snowman tidak ada lapisan seperti itu pada mesin Pac-Man. Tidak ada loader - gim ini berada dalam ROM eksekusi di tempat. Tidak ada manajemen memori - semuanya statis. Tidak ada "layanan"; gim mengakses perangkat keras secara langsung dan tidak ada byte kode pada sistem yang bukan bagian dari gim dan ditulis untuk gim.
hobbs

38

Sepertinya Anda membingungkan "perilaku tidak terdefinisi" dan "kesalahan segmentasi".

Tidak ada yang namanya segfault tidak tertangani. Kesalahan segmentasi adalah penanganan kesalahan, menurut definisi.

Jika Anda tidak memiliki OS yang mendeteksi akses memori buruk dan menghentikan proses untuk keselamatan, maka Anda tidak memiliki kesalahan segmentasi.

Jika ada, maka, ini adalah contoh yang cukup bagus tentang bagaimana UB tidak selalu menghasilkan segfault.


2
Untuk lebih tepatnya OS dapat memutuskan untuk membunuh (yaitu proses yang tidak dapat disembuhkan). OS modern bukannya memilih untuk menghentikannya , yang dapat ditangkap dan ditangani, FWIW.
edmz

@black: Bukankah itu yang saya katakan?
Lightness Races dengan Monica

15
Bahkan mungkin bukan "perilaku tidak terdefinisi". Jika Pacman ditulis dalam rakitan murni, maka kode melakukan apa yang diperintahkan untuk dilakukan dengan cara yang benar-benar ditentukan. Bukan perilaku yang tidak jelas, tetapi hanya bug. Dengan demikian, kode akan menjalankan cara yang sama persis berjalan pada sistem apa pun yang memiliki port sempurna dari chipset yang mendasarinya.
Gort the Robot

@ SevenBurnap: Itu benar.
Lightness Races dengan Monica

@ hitam Apa perbedaan antara 'membunuh' dan 'mengakhiri'? Selain fakta bahwa 'membunuh' biasanya kosa kata UNIX, dan 'mengakhiri' lebih banyak Windows-y?
Brandin

24

Tidak satu pun dari istilah ini yang sesuai untuk bug dalam game arcade yang diprogram dalam bahasa assembly dan berjalan tanpa manfaat dari perangkat keras perlindungan memori atau sistem operasi.

"Perilaku tidak terdefinisi" adalah istilah termutakhir dalam bahasa C dan yang terkait, diciptakan oleh komite standar C pada tahun 1989. Kode memiliki perilaku tidak terdefinisi ketika spesifikasi bahasa tidak menentukan apa yang akan dilakukan. Tidak ada hal seperti itu dalam bahasa assembly Z80: efek dari setiap opcode dengan setiap input yang mungkin didefinisikan dengan baik. Arti bahasa Inggris konvensional dari "perilaku tidak terdefinisi" dapat dibaca untuk diterapkan - kill screen adalah perilaku yang tidak didefinisikan oleh orang-orang yang menulis game - tetapi saya tidak akan menggunakannya dalam konteks ini karena terlalu mungkin memberikan yang salah kesan.

"Segmentasi fault" adalah istilah termutakhir dalam POSIX, yang pada akhirnya diturunkan dari jargon pemrograman sistem PDP. Kesalahan segmentasi terjadi ketika suatu program mencoba mengakses alamat memori yang tidak "dipetakan" ke apa pun: perangkat keras dan sistem operasi mendeteksi ini dan mematikan program yang tidak berfungsi, dengan cara yang ditentukan dengan hati-hati yang memungkinkan program kesempatan untuk pulih . Sesuatu sepertiini bisa terjadi sebagai akibat dari bug dalam program permainan Pac-Man, karena papan sirkuit Pac-Man hanya mengisi sedikit kurang dari setengah ruang alamat 64kB Z80 dengan ROM, RAM, dan periferal, tapi saya belum tahu t tidak dapat mengetahui apa yang akan dilakukan perangkat keras nyata jika perangkat lunak berusaha mengakses memori yang belum dipetakan. Apa pun yang akan dilakukan, itu akan tidak pantas untuk menggambarkan sebagai "kesalahan segmentasi", karena "sistem operasi" untuk Pac-Man (sejauh itu bahkan memiliki satu) bukan merupakan implementasi dari Unix dan, sekali lagi, itu akan memberi kesan yang salah.

Bug level 256, sementara itu, tidak mengakses memori yang belum dipetakan, jadi ini bisa diperdebatkan.

Adalah akurat untuk mengatakan bahwa permainan memiliki bug yang bermanifestasi setelah naik ke level 256. Juga akurat untuk mengatakan bahwa akar penyebab bug adalah bilangan bulat bilangan bulat , dan bahwa konsekuensinya adalah kerusakan memori (atau, setara, pelanggaran) dari memori dan jenis keamanan ). Ini semua adalah istilah CS tujuan umum yang didefinisikan tanpa mengacu pada bahasa atau lingkungan OS tertentu.

Juga akurat untuk mengamati bahwa efek bug mirip dengan efek, dalam lingkungan modern, bug-korupsi memori yang tidak memprovokasi kesalahan segmentasi. Jika Anda membaca salah satu luncuran eksploitasi Project Zero , Anda akan melihat kesamaan yang luar biasa dengan analisis Don Hodges tentang layar pembunuh Pac-Man .

Perhatikan bahwa emulator yang tidak dengan setia mereproduksi layar kill ketika memberi makan ROM Pac-Man tidak meniru perangkat keras game dengan benar.


Ungkapan, "perilaku tidak terdefinisi" mungkin belum pernah digunakan dalam cetakan dengan cara yang tepat sebelum 1989, tetapi gagasan bahwa frasa itu menggambarkan sama tuanya dengan pemrograman itu sendiri. Common Lisp: The Language (Digital Press, 1984; ISBN 0-932376-41-X) menggunakan kata-kata "itu adalah kesalahan" untuk mengartikan hal yang persis sama. Misalnya, "Ini adalah kesalahan untuk memanggil fungsi ini dengan x <0" berarti bahwa programmer tidak boleh membiarkan fungsi dipanggil dengan x <0 dan, bahwa implementasi diizinkan untuk melakukan apa pun yang ingin dilakukan oleh pelaksana jika programmer aplikasi tidak mematuhi.
Solomon Slow

5
@jameslarge Saya mengerti maksud Anda, tapi saya masih berpikir itu adalah kesalahan untuk menerapkan konsep ini ke Pac-Man. Kita dapat mengatakan bahwa kill screen adalah bug karena gamenya jelas tidak berperilaku seperti yang dimaksudkan perancang. Kita tidak bisa mengatakan bahwa permainan telah memprovokasi perilaku tidak terdefinisi , karena tidak ada spesifikasi bahasa untuk mengatakan "dalam keadaan apa pun programmer dapat melakukan X" untuk nilai X apa pun (saya kira penggunaan opcode tidak berdokumen Z80 mungkin memenuhi syarat, kecuali bahwa banyak permainan arcade melakukan menggunakan mereka dan AFAIK mereka semua memiliki efek diprediksi).
zwol

1
Ini jawaban terbaik. "Perilaku tidak terdefinisi" berarti bahwa pembuat kode menulis kode yang hasilnya tidak dapat diramalkan berdasarkan standar. Jika Pacman ditulis dalam perakitan Z80 (dan saya percaya itu) maka kode yang ditulis memiliki makna yang sepenuhnya ditentukan terlepas dari apakah program melakukan sesuatu yang tidak diinginkan oleh pembuat kode.
Gort the Robot

8

Bug level-256 dalam Pac Man menghasilkan program membaca data yang berada di luar akhir tabel yang dimaksud, tetapi masih dapat dibaca , dan menulis ke bagian layar yang berada di luar yang ingin dituliskan oleh program, tetapi masih berada dalam area layar yang diizinkan untuk ditulis oleh program . Tidak ada area memori lain yang terpengaruh.

Alasan bug membuat game tidak dapat dimainkan adalah karena mesin menentukan kapan seorang pemain memakan titik-titik dengan memeriksa apa yang ada di layar, dan memutuskan bahwa levelnya sudah selesai ketika pemain telah memakan 244 titik. Dengan menimpa bagian layar, bug membuat pemain tidak bisa makan 244 titik; akibatnya, permainan tidak akan pernah memberi kredit kepada pemain dengan menyelesaikan level dan memuat ulang layar dengan titik-titik.


1
Ketika Anda bunuh diri di level 256, titik-titik itu muncul kembali, tetapi Anda tidak kehilangan apa pun.
Ave

@ardaozkal: Rutin level-draw menghapus lebih dari 100 titik dan menarik beberapa. Jika seorang pemain memiliki cukup banyak nyawa, pada akhirnya akan mungkin untuk makan cukup banyak titik untuk naik level, tetapi itu akan membutuhkan lebih dari 30 nyawa.
supercat

Saya ingat menonton video di mana pemain memiliki kehidupan yang cukup, dan dia berhasil ... dan saya baru saja menemukannya .
Ave

@ardaozkal: Berapa banyak nyawa yang diperlukan untuk menghapus level, dan berapa banyak nyawa yang bisa didapatkan pemain dengan mesin yang tidak dimodifikasi ?
supercat

Anda bahkan tidak bisa mencapai level 256 pada mesin yang tidak dimodifikasi.
Ave

1

Seperti yang dikatakan sebelumnya tidak itu bukan kesalahan seg. Saya akan menambahkan mengapa masalah terjadi: ini meluap .

Nomor level disimpan pada byte sehingga kisarannya adalah 0-255. Setiap kali Anda menyelesaikan level, penghitung bertambah. Pada level 256, penghitung sebenarnya adalah 0 karena overflow.

Namun permainan mencoba untuk menampilkan beberapa buah di bagian bawah level. Jumlah / jenis buah tergantung pada levelnya. Rumus menampilkan satu buah per level jadi di bawah level 8. Menurut penghitung Anda berada di level 0 jadi di bawah 8. Tes itu benar dan Anda harus mencetak 255 buah (nilai level lama). Yang tidak mungkin dan memberikan layar glitched ini.

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.