“ ระดับ 256 บั๊ก” ในเกม Pacman สามารถถูกพิจารณาว่าเป็นเซกฟอลต์ที่ไม่มีการจัดการได้หรือไม่?


51

ฉันกำลังพยายามอธิบายข้อผิดพลาดในการแบ่งกลุ่มกับใครบางคนและฉันกำลังคิดถึงระดับ kill-screen ระดับ 256 ใน Pacman และวิธีที่มันถูกทริกเกอร์โดยจำนวนเต็มล้นและพฤติกรรมที่คล้ายคลึงกันคือ ความผิด

ฉันต้องการบอกว่านี่เป็นตัวอย่างที่ดีของสิ่งที่ฉันเรียกว่า "segfault ที่ไม่สามารถจัดการได้" แต่ฉันอยากได้ความเห็นที่สองก่อนที่ฉันจะแพร่กระจายข้อมูลที่ผิดไป

ฉันพยายามค้นหามัน แต่ทั้งหมดที่ฉันได้รับคือเอกสารเกี่ยวกับตัวมันเองรวมถึงความร่วมมือระหว่าง Hipster Whale และ Namco

ดังนั้นคุณจะพิจารณาพฤติกรรมในระดับ 256 ของ Pacman ว่าเป็นตัวอย่างของการละเมิดการแบ่งส่วนที่ไม่ได้จัดการหรือไม่


3
นี่คือคำอธิบายข้อผิดพลาดที่แน่นอนพร้อมกับแพตช์เพื่อแก้ไข: donhodges.com/how_high_can_you_get2.htm
abligh

26
ความผิดพลาดของการแบ่งกลุ่มได้รับการยกระดับโดยฮาร์ดแวร์เพื่อหลีกเลี่ยงการเข้าถึงหน่วยความจำที่ผิดกฎหมาย ฉันไม่มีความเชี่ยวชาญใน Pacman แต่ฮาร์ดแวร์ที่ใช้ในแทบจะไม่มีคุณสมบัติความปลอดภัยนี้ในการเริ่มต้น
BlueRaja - Danny Pflughoeft

3
อ้างอิงจากวิกิพีเดีย Pacman ใช้ Z80 Z80s ไม่ได้มีการป้องกันหน่วยความจำ
Gort the Robot

ไม่ใช่ segfault - ระบบไม่มีการป้องกันหน่วยความจำในรูปแบบใด ๆ ประสบการณ์ความผิดพลาดPac-Manที่ระดับ 256 เป็นเพียงแค่จำนวนเต็มล้นที่ไม่สามารถจัดการได้อย่างถูกต้องโดยรหัสของเกม
bwDraco

3
FYI ฉันไม่คิดว่านี่จะเป็นข้อผิดพลาด ข้อบกพร่องคือความล้มเหลวหรือความผิดพลาดในโปรแกรมคอมพิวเตอร์หรือระบบที่ทำให้เกิดผลลัพธ์ที่ไม่ถูกต้องหรือไม่คาดคิดหรือทำงานในลักษณะที่ไม่ได้ตั้งใจ มันถูกตั้งโปรแกรมโดยเจตนาเนื่องจากรู้สึกว่าไม่มีใครไปถึงระดับนั้น ในความเป็นจริงการออกแบบซอฟต์แวร์ที่ไม่ดี
Keltari

คำตอบ:


113

ไม่อย่างแน่นอน.

การเข้าถึงที่อยู่หน่วยความจำที่คุณไม่ได้จัดสรรมักเป็นข้อผิดพลาดในการเขียนโปรแกรม และการแสดงข้อมูลที่คุณได้รับจากมันก่อให้เกิดพฤติกรรมที่ไม่ได้กำหนดซึ่งมีความแม่นยำมาก ฉันไม่รู้ว่าแพลตฟอร์มต้นฉบับของ Pac-man ถูกเขียนขึ้นมาอย่างไร แต่ฉันค่อนข้างแน่ใจว่ามันแสดงพฤติกรรมนี้เหมือนกับเครื่อง von Neumann อื่น ๆ

อย่างไรก็ตาม "การแบ่งส่วนความผิดพลาด" เป็นคำศัพท์ทางเทคนิคสำหรับเงื่อนไขที่เฉพาะเจาะจงมากขึ้น มันจะเกิดขึ้นเมื่อคอมพิวเตอร์ตรวจพบว่าสิ่งนี้เกิดขึ้นโดยอัตโนมัติและยุติกระบวนการแทนที่จะปล่อยให้พฤติกรรมที่ไม่ได้กำหนดเกิดขึ้น สิ่งนี้ต้องการรูปแบบหน่วยความจำเฉพาะ (แบ่งส่วน) ที่มีการแท็กความเป็นเจ้าของที่ซับซ้อน ฉันไม่คิดว่า 1980 มีเกมอาเขตนั้นและในความเป็นจริงพฤติกรรมของเกมที่แสดงให้เห็นว่าข้อผิดพลาดก็ไม่ได้ตรวจพบและไม่ได้กำหนดพฤติกรรมไม่เกิดขึ้น


19
@ B1KMusic: คุณกำลังถามจริง ๆ "เป็นรหัสนี้ 'บั๊ก' เป็นตัวอย่างของการเรียกใช้พฤติกรรมที่ไม่ได้กำหนดผ่านการเข้าถึงหน่วยความจำนอกขอบเขต" และคำตอบคือ "ใช่" เหตุผลใด ๆ เกี่ยวกับการจับการเพิกเฉยไม่ได้รับสัญญาณ SIGSEGV เป็นเพียงเรื่องที่สับสน
การแข่งขัน Lightness กับโมนิก้า

5
@ B1KMusic การบัฟเฟอร์ที่โอเวอร์รันไม่ทั้งหมดส่งผลให้เกิด segfault ขึ้นอยู่กับวิธีการจัดสรรหน่วยความจำ หากหน่วยความจำถูกจัดสรรแบบคงที่ (บัฟเฟอร์ขนาดใหญ่หนึ่งแบ่งด้วยตนเองในโซนที่แตกต่างกัน) และพื้นที่ที่อยู่ด้านหลังระดับสุดท้ายถูกนำมาใช้สำหรับบางสิ่งบางอย่าง (เช่นกราฟิกสไปรท์) แล้วมันจะไม่ segfault
วงล้อประหลาด

6
ระบบอาร์เคดเก่า ๆ เหล่านั้นใช้ระบบปฏิบัติการดั้งเดิมที่ทำให้เกมสามารถควบคุมฮาร์ดแวร์ได้อย่างสมบูรณ์คล้ายกับดอสรุ่นแรก แนวคิดของ segfault ในสถาปัตยกรรมประเภทนั้นไม่ใช่แบบเริ่มต้นเนื่องจากถือว่ากระบวนการหนึ่งที่ทำงาน (Pac-Man) ไม่ได้เป็นเจ้าของหน่วยความจำทั้งหมด สำหรับข้อมูลเพิ่มเติมหนึ่งสามารถอ่านได้ในโครงการ MAMEและประวัติของมัน

20
พฤติกรรมที่ไม่ได้กำหนดไม่ได้เป็นคุณสมบัติของเครื่อง von Neumann แต่เป็นคุณสมบัติของ C ซึ่งเป็นภาษาการเขียนโปรแกรม โปรแกรมที่เขียนด้วยภาษาแอสเซมบลีไม่สามารถแสดงลักษณะการทำงานที่ไม่ได้กำหนดได้เนื่องจากพฤติกรรมของคำสั่งภาษาแอสเซมบลีมักจะถูกกำหนดไว้อย่างดีเสมอ (แม้ว่าบางครั้งผลลัพธ์จะไม่ได้รับการระบุ)
Dietrich Epp

8
@Snowman ไม่มีเลเยอร์ดังกล่าวในเครื่อง Pac-Man ไม่มีตัวโหลด - เกมอยู่ในรันไทม์แทนการวาง ไม่มีการจัดการหน่วยความจำ - ทุกอย่างคงที่ ไม่มี "บริการ"; เกมเข้าถึงฮาร์ดแวร์โดยตรงและไม่มีรหัสไบต์ในระบบที่ไม่ได้เป็นส่วนหนึ่งของเกมและเขียนขึ้นสำหรับเกม
ฮอบส์

38

ดูเหมือนว่าคุณสับสน "พฤติกรรมที่ไม่ได้กำหนด" และ "การแบ่งกลุ่มผิด"

ไม่มีสิ่งเช่น segfault ที่ไม่สามารถจัดการได้ ความผิดพลาดของการแบ่งส่วนคือการจัดการข้อผิดพลาดตามคำนิยาม

หากคุณไม่มีระบบปฏิบัติการที่ตรวจพบการเข้าถึงหน่วยความจำไม่ดีและยุติกระบวนการเพื่อความปลอดภัยแสดงว่าคุณไม่มีข้อผิดพลาดในการแบ่งส่วน

หากมีสิ่งใดนี่เป็นตัวอย่างที่ดีว่า UB ไม่ได้ส่งผลให้เกิด segfault เสมอไป


2
เพื่อความแม่นยำของระบบปฏิบัติการอาจตัดสินใจที่จะฆ่า (เช่นไม่สามารถกู้คืนได้) กระบวนการ ระบบปฏิบัติการโมเดิร์นแทนต้องการที่จะยุติมันซึ่งอาจถูกจับและจัดการ FWIW
edmz

@black: นั่นคือสิ่งที่ฉันพูดไม่ได้เหรอ?
การแข่งขัน Lightness กับโมนิก้า

15
มันอาจไม่ได้เป็น "พฤติกรรมที่ไม่ได้กำหนด" ถ้า Pacman ถูกเขียนด้วยชุดประกอบที่บริสุทธิ์รหัสก็จะทำตามที่ได้รับคำสั่งให้ทำอย่างถูกต้อง ไม่ใช่พฤติกรรมที่ไม่ได้กำหนด แต่เป็นเพียงข้อบกพร่อง ดังนั้นโค้ดจะทำงานแบบเดียวกับที่ใช้กับระบบที่มีพอร์ตที่สมบูรณ์แบบของชิปเซ็ตพื้นฐาน
Gort the Robot

@StevenBurnap: นั่นเป็นความจริง
การแข่งขัน Lightness กับโมนิก้า

@black ความแตกต่างระหว่าง 'kill' และ 'ยุติ' คืออะไร? นอกเหนือจากข้อเท็จจริงที่ว่า 'kill' เป็นคำศัพท์ UNIX และ 'ยุติ' เป็น Windows-y มากกว่านี้หรือไม่?
Brandin

24

ข้อกำหนดเหล่านี้ไม่เหมาะสำหรับข้อบกพร่องในเกมอาร์เคดที่ตั้งโปรแกรมในภาษาแอสเซมบลีและทำงานโดยไม่ได้รับประโยชน์จากฮาร์ดแวร์หรือระบบปฏิบัติการป้องกันหน่วยความจำ

"พฤติกรรมที่ไม่ได้กำหนด" เป็นคำศัพท์ในภาษา C และภาษาที่เกี่ยวข้องประกาศเกียรติคุณโดยคณะกรรมการมาตรฐาน C ในปี 1989 รหัสมีพฤติกรรมที่ไม่ได้กำหนดเมื่อข้อกำหนดภาษาไม่ได้กำหนดสิ่งที่จะทำ ไม่มีสิ่งนั้นในภาษาแอสเซมบลี Z80: เอฟเฟกต์ของ opcode ทุกตัวที่มีอินพุตที่เป็นไปได้ทั้งหมดได้รับการกำหนดไว้อย่างดี ความหมายทั่วไปของภาษาอังกฤษของ "พฤติกรรมที่ไม่ได้กำหนด" สามารถอ่านได้เพื่อนำไปใช้ - หน้าจอการฆ่าเป็นพฤติกรรมที่ไม่ได้กำหนดโดยคนที่เขียนเกม - แต่ฉันจะไม่ใช้มันในบริบทนี้เพราะมันมีแนวโน้มที่จะผิด ความประทับใจ

"การแบ่งส่วนความผิดพลาด" เป็นคำศัพท์ที่ทันสมัยใน POSIX ซึ่งได้มาในที่สุดจากศัพท์แสงการเขียนโปรแกรมระบบ PDP ความผิดพลาดของการแบ่งกลุ่มเกิดขึ้นเมื่อโปรแกรมพยายามเข้าถึงที่อยู่หน่วยความจำที่ไม่ได้ "แมป" กับสิ่งใด: ฮาร์ดแวร์และระบบปฏิบัติการตรวจพบสิ่งนี้และปิดโปรแกรมที่ทำงานผิดพลาดด้วยวิธีที่กำหนดอย่างระมัดระวังซึ่งทำให้โปรแกรมมีโอกาสกู้คืน . บางอย่างเช่นสิ่งนี้อาจเกิดขึ้นจากข้อผิดพลาดในโปรแกรมเกม Pac-Man เนื่องจากแผงวงจร Pac-Man บรรจุเพียงน้อยกว่าครึ่งหนึ่งของพื้นที่แอดเดรส 64kB 64kB ของ Z80 ที่มี ROM, RAM และอุปกรณ์ต่อพ่วง แต่ฉันยังไม่ได้ ไม่สามารถค้นหาว่าฮาร์ดแวร์จริงจะทำอย่างไรหากซอฟต์แวร์พยายามเข้าถึงหน่วยความจำที่ไม่ได้แมป แม้ว่าสิ่งที่มันจะทำมันจะไม่เหมาะสมที่จะอธิบายว่าเป็น "การแบ่งส่วนความผิด" เพราะ "ระบบปฏิบัติการ" สำหรับ Pac-Man (เท่าที่มันมีหนึ่ง) ไม่ได้ดำเนินการตาม Unix และอีกครั้งมัน จะให้ความประทับใจที่ผิด

ข้อผิดพลาดระดับ 256 ในขณะเดียวกันไม่สามารถเข้าถึงหน่วยความจำที่ไม่ได้แมปดังนั้นจึงเป็นข้อสงสัย

มันมีความถูกต้องที่จะบอกว่าเกมนี้มีบั๊กที่ปรากฎเมื่อใกล้ถึงเลเวล 256 นอกจากนี้ยังถูกต้องที่จะบอกว่าสาเหตุของข้อผิดพลาดนั้นคือจำนวนเต็มล้นและผลที่ตามมาคือหน่วยความจำเสียหาย (หรือเทียบเท่า ของหน่วยความจำและความปลอดภัยประเภท ) เหล่านี้เป็นข้อกำหนด CS สำหรับวัตถุประสงค์ทั่วไปที่กำหนดโดยไม่มีการอ้างอิงถึงภาษาหรือสภาพแวดล้อมระบบปฏิบัติการใด ๆ

นอกจากนี้ยังมีความถูกต้องที่จะสังเกตว่าผลกระทบของข้อบกพร่องนั้นคล้ายกับผลกระทบภายในสภาพแวดล้อมที่ทันสมัยของข้อบกพร่องการทุจริตหน่วยความจำที่ไม่ก่อให้เกิดข้อผิดพลาดการแบ่งส่วน ถ้าคุณอ่านใด ๆ ของโครงการศูนย์ใช้ประโยชน์จาก writeups คุณจะเห็นความคล้ายคลึงกันที่โดดเด่นเพื่อดอนฮอดจ์การวิเคราะห์ของ Pac-Man ฆ่าหน้าจอ

โปรดทราบว่าอีมูเลเตอร์ที่ไม่สร้างหน้าจอฆ่าซ้ำโดยสุจริตเมื่อป้อน Pac-Man ROM ไม่ได้จำลองฮาร์ดแวร์ของเกมอย่างถูกต้อง


วลี "พฤติกรรมที่ไม่ได้กำหนด" อาจไม่ได้ถูกนำมาใช้ในการพิมพ์ในลักษณะที่ถูกต้องก่อนปี 1989 แต่แนวคิดที่ว่าวลีดังกล่าวนั้นเก่าแก่กว่าการเขียนโปรแกรมเอง เสียงกระเพื่อมสามัญ: ภาษา (Digital Press, 1984; ISBN 0-932376-41-X) ใช้คำว่า "มันเป็นข้อผิดพลาด" เพื่อหมายถึงสิ่งเดียวกัน เช่น "มันเป็นข้อผิดพลาดในการเรียกใช้ฟังก์ชันนี้ด้วย x <0" หมายความว่าโปรแกรมเมอร์ไม่ควรอนุญาตให้เรียกใช้ฟังก์ชันด้วย x <0 และการใช้งานนั้นได้รับอนุญาตให้ทำสิ่งใดก็ตามที่ผู้ใช้ต้องการทำ แอปพลิเคชันโปรแกรมเมอร์ไม่ปฏิบัติตาม
โซโลมอนช้า

5
@ James ขนาดใหญ่ฉันเข้าใจสิ่งที่คุณหมายถึง แต่ฉันยังคงคิดว่ามันเป็นความผิดพลาดที่จะนำแนวคิดนี้ไปใช้กับ Pac-Man เราสามารถพูดได้ว่าหน้าจอ kill เป็นข้อผิดพลาดเพราะเกมเห็นได้ชัดว่าไม่ได้ทำงานตามที่ผู้ออกแบบต้องการ เราไม่สามารถพูดได้ว่าเกมดังกล่าวก่อให้เกิดพฤติกรรมที่ไม่ได้กำหนดเนื่องจากไม่มีข้อกำหนดภาษาที่จะพูดว่า "โปรแกรมเมอร์ไม่ควรทำ X" ภายใต้สถานการณ์ใด ๆ สำหรับค่า X ใด ๆ (ฉันคิดว่าการใช้ Opocode ที่ไม่มีเอกสารของ Z80 อาจมีคุณสมบัติ ความอุดมสมบูรณ์ของเกมอาเขตได้ใช้เหล่านั้นและ AFAIK พวกเขาทั้งหมดมีผลกระทบที่คาดเดาได้).
zwol

1
นี่คือคำตอบที่ดีที่สุด "พฤติกรรมที่ไม่ได้กำหนด" หมายถึงโค้ดที่เขียนโค้ดซึ่งผลลัพธ์ไม่สามารถบอกล่วงหน้าได้ตามมาตรฐาน ถ้า Pacman ถูกเขียนในชุด Z80 (และฉันเชื่อว่ามันเป็น) แล้วรหัสที่เขียนนั้นมีความหมายที่กำหนดไว้ทั้งหมดโดยไม่คำนึงว่าโปรแกรมทำสิ่งที่ coder ไม่ได้ตั้งใจหรือไม่
Gort the Robot

8

ข้อบกพร่องระดับ 256 ใน Pac Man ส่งผลให้ข้อมูลการอ่านโปรแกรมซึ่งอยู่นอกเหนือจากจุดสิ้นสุดของตารางที่ตั้งใจ แต่ยังคงเป็นที่เก็บข้อมูลที่สามารถอ่านได้และการเขียนไปยังส่วนของหน้าจอซึ่งอยู่นอกเหนือจากที่โปรแกรมตั้งใจจะเขียนยังคงอยู่ในพื้นที่ของหน้าจอที่โปรแกรมอนุญาตให้เขียนได้ ไม่มีผลกระทบด้านอื่นของหน่วยความจำ

เหตุผลที่บั๊กทำให้เกมเล่นไม่ได้คือเครื่องกำหนดว่าเมื่อผู้เล่นกำลังกินจุดโดยการตรวจสอบสิ่งที่อยู่บนหน้าจอและตัดสินใจว่าระดับนั้นเสร็จสมบูรณ์เมื่อผู้เล่นกินจำนวน 244 จุด โดยการเขียนทับส่วนหนึ่งของหน้าจอข้อผิดพลาดทำให้ผู้เล่นไม่สามารถกินได้ 244 จุด; ดังนั้นเกมจะไม่ให้เครดิตผู้เล่นเมื่อสำเร็จระดับและโหลดหน้าจอใหม่ด้วยจุด


1
เมื่อคุณฆ่าตัวตายในระดับ 256 จุดจะเกิดใหม่ แต่คุณจะไม่แพ้
Ave

@ardaozkal: รูทีนการวาดระดับจะลบจุดมากกว่า 100 จุดและดึงออกมาสองสามจุด หากผู้เล่นมีชีวิตที่เพียงพอในที่สุดมันก็เป็นไปได้ที่จะกินจุดมากพอที่จะเลื่อนระดับ แต่ก็ต้องมีมากกว่า 30 ชีวิต
supercat

ผมจำได้ว่าดูวิดีโอที่ผู้เล่นมีชีวิตพอและเขาจัดการมัน ... และฉันเพิ่งพบมัน
Ave

@ardaozkal: ต้องมีกี่ชีวิตในการเคลียร์เลเวลและผู้เล่นสามารถรับเครื่องที่ไม่มีการดัดแปลงได้กี่ชีวิต?
supercat

คุณไม่สามารถไปถึงระดับ 256 บนเครื่องที่ไม่ได้ทำการแก้ไขได้
Ave

1

อย่างที่บอกไว้ก่อนหน้านี้ว่าไม่ใช่ความผิดของ seg ฉันจะเพิ่มทำไมปัญหาเกิดขึ้น: มันเป็นล้น

หมายเลขระดับจะถูกเก็บไว้ในไบต์ดังนั้นช่วงคือ 0-255 ทุกครั้งที่คุณกรอกระดับตัวนับจะเพิ่มขึ้น ที่ระดับ 256 ตัวนับเป็นจริง 0 เนื่องจากการล้น

อย่างไรก็ตามเกมพยายามที่จะแสดงผลไม้บางอย่างที่ด้านล่างของระดับ หมายเลขผลไม้ / ประเภทขึ้นอยู่กับระดับ สูตรแสดงผลไม้หนึ่งผลต่อระดับที่เสร็จแล้วภายใต้ระดับ 8 ตามตัวนับคุณอยู่ในระดับ 0 ดังนั้นภายใต้ 8 การทดสอบจะเป็นจริงแล้วและคุณต้องพิมพ์ 255 ผลไม้ (ค่าระดับเก่า) ซึ่งเป็นไปไม่ได้และให้หน้าจอผิดพลาดนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.