パックマンのゲームの「レベル256バグ」は、未処理のセグメンテーション違反と見なすことができますか?


51

私はセグメンテーションフォールトを誰かに説明しようとしていますが、Pacmanのレベル256キルスクリーン、整数オーバーフローによってトリガーされる方法、およびセグメンテーションで説明されている「不明な状態」と動作がどのように似ているかを考えていました障害。

これは私が「未処理のセグメンテーション違反」と呼ぶものの良い例だと言いたいのですが、誤った情報を広める可能性がある前にセカンドオピニオンを得たいと思います。

調べてみましたが、バグ自体に関するドキュメントと、Hipster WhaleとNamcoの間のコラボレーションだけが手に入ります。

それで、Pacmanのレベル256の動作は、未処理のセグメンテーション違反の例だと考えますか?


3
バグの正確な説明と、それを修正するパッチを次に示し
abligh

26
不正なメモリアクセスを回避するために、ハードウェアによってセグメンテーションエラーが発生します。私はPacmanの専門家ではありませんが、Pacmanが実行されていたハードウェアには、最初からこの安全機能がありませんでした。
BlueRaja-ダニーPflughoeft

3
ウィキペディアによると、パックマンはZ80を使用しました。Z80sにはメモリ保護機能がありませんでした。
ロボット

これはセグメンテーション違反ではありません。システムにはメモリ保護の形式がありませんでした。レベル256でパックマンが経験する障害は、ゲームのコードで正しく処理されない整数オーバーフローです。
bwDraco

3
参考までに、これがバグだとは思わない。バグは、コンピュータプログラムまたはシステムの障害または障害であり、不正確または予期しない結果を生成したり、意図しない方法で動作したりします。それはして意図的にそれは誰もがそのレベルに到達しないだろうと感じられたことから、そのようにプログラムされています。実際には、その貧弱なソフトウェア設計です。
ケルタリ

回答:


113

絶対にありません。

割り当てなかったメモリアドレスへのアクセスは、常にプログラミングエラーです。そして、あなたがそこから得た情報に基づいて行動することは未定義の振る舞いを生み出します。オリジナルのパックマンがどのプラットフォーム向けに書かれたかはわかりませんが、他のフォンノイマンマシンと同じようにこの動作を示したと確信しています。

ただし、「セグメンテーション障害」は、より具体的な状態の技術用語です。未定義の動作を許可するのではなく、これが発生したことをコンピューターが自動的に検出してプロセスを終了すると発生します。これには、洗練された所有権タグ付けを備えた特定の(セグメント化された)メモリモデルが必要です。1980年のアーケードゲームにはそれがなかったと思います。実際、ゲームの動作は、エラーが検出され、未定義の動作発生したことを示唆してます。


19
@ B1KMusic:あなたは本当に「このコードは「バグ」であり、範囲外のメモリアクセスを通じて未定義の動作を呼び出す例ですか」と答えています。答えは「はい」です。SIGSEGVシグナルを捕捉、無視、取得しないことについての合理化は、混乱を招く問題です。
モニカとの軽さのレース

5
@ B1KMusicがすべてのバッファオーバーランでセグメンテーション違反になるわけではありません。メモリの割り当て方法によって異なります。メモリが静的に割り当てられ(1つの大きなバッファーが異なるゾーンに手動で分割される)、最後のレベルのすぐ後ろの領域が何か(スプライトグラフィックスなど)に使用された場合、セグメンテーション違反は発生しません。
ラチェットフリーク

6
これらの古いアーケードシステムは、DOSの初期バージョンと同様に、ゲームにハードウェアをほぼ完全に制御できるプリミティブOSを使用していました。そのタイプのアーキテクチャでのセグメンテーション違反のアイデアは、1つの実行中のプロセス(Pac-Man)がすべてのメモリを所有していないと想定しているため、非スターターです。詳細については、MAMEプロジェクトとその歴史をご覧ください。

20
未定義の動作は、フォンノイマンマシンのプロパティではなく、プログラミング言語Cのプロパティです。アセンブリ言語命令の動作は常に明確に定義されているため、アセンブリ言語で記述されたプログラムは未定義の動作を示すことはできません(結果が不特定の場合でも)。
ディートリッヒエップ

8
@Snowmanパックマンマシンにはそのようなレイヤーはありません。ローダーはありません。ゲームはインプレース実行ROMにあります。メモリ管理はありません。すべてが静的です。「サービス」はありません。ゲームはハードウェアに直接アクセスし、システムにはゲームの一部ではなくゲーム用に記述されたコードのバイトはありません。
ホッブズ

38

「未定義の動作」と「セグメンテーション違反」を混同しているようです。

未処理のセグメンテーション違反などはありません。セグメンテーション違反、定義によるエラー処理です。

不正なメモリアクセスを検出し、安全のためにプロセスを終了したOSがない場合、セグメンテーションエラーはありません。

どちらかといえば、これはUB 常にセグメンテーション違反を引き起こすとは限らない方法のかなり良い例です。


2
正確に言うと、OS プロセスを強制終了(回復不能)する場合があります。代わりに、現代のOS はFWIWをキャッチして処理する可能性があるため、終了することを好みます。
edmz

@black:それは私が言ったことではありませんか?
モニカとの軽さのレース

15
「未定義の動作」でさえないかもしれません。Pacmanが純粋なアセンブリで記述されている場合、コードは完全に定義された方法で指示されたことを正確に実行しました。未定義の動作ではなく、単なるバグです。そのため、コードは、基盤となるチップセットの完全なポートを備えたシステム上で実行されるのとまったく同じ方法で実行されます。
ロボットをゲット

@StevenBurnap:それは本当です。
モニカとの軽さレース

@black「kill」と「terminate」の違いは何ですか?「kill」は通常UNIXの語彙であり、「terminate」はより多くのWindows-yであるという事実以外に?
ブランディン

24

これらの用語はどちらも、アセンブリ言語でプログラムされたアーケードゲームのバグには適切ではなく、メモリ保護ハードウェアまたはオペレーティングシステムの利点なしで実行されます。

「未定義の動作」は、1989年にC標準委員会によって作成された、Cおよび関連言語の専門用語です。言語仕様何をするかを定義しない場合、コードの動作は未定義です。Z80アセンブリ言語にはそのようなことはありません。すべての可能な入力でのすべてのオペコードの効果は明確に定義されています。「未定義の動作」の従来の英語の意味は適用するために読むことができます-キル画面はゲームを書いた人によって定義されていない動作です-しかし、私はこの文脈ではそれを使用しません印象。

「セグメンテーションフォールト」はPOSIXの専門用語であり、最終的にPDPシステムプログラミングの専門用語から派生しています。プログラムが何かに「マッピング」されていないメモリアドレスにアクセスしようとすると、セグメンテーションフォールトが発生します。ハードウェアとオペレーティングシステムがこれを検出し、プログラムが回復できるよう慎重に定義された方法で誤動作しているプログラムをシャットダウンします。のようなものこれは、Pac-Manゲームボードのバグの結果として発生した可能性があります。これは、Pac-Manの回路基板が、ROM、RAM、および周辺機器を含むZ80の64kBアドレス空間の半分よりも少しだけ少ないためですソフトウェアがマップされていないメモリにアクセスしようとした場合、実際のハードウェアが何をするかを知ることができました。それはどうしたらどのような(それも程度のパックマンのための「オペレーティングシステム」ので、しかし、「セグメンテーション違反」として記述することが不適切であると考えている 1)がありませんもう一度、Unixのの実装と、それは、間違った印象を与えるでしょう。

一方、レベル256のバグは、マップされていないメモリにアクセスしないため、意味がありませ

ゲームにはレベル256に進むと現れるバグがあると言うのは正確です。バグの根本的な原因は整数オーバーフローであり、その結果はメモリ破損(または同等に違反)であると言うことも正確ですメモリと型の安全性)。これらはすべて、特定の言語やOS環境を参照せずに定義された汎用CS用語です。

また、バグの影響が、セグメンテーションフォールトを引き起こさないメモリ破損バグの現代環境内の影響に類似していることを観察することも正確です。Project Zeroのエクスプロイトの記事を読むと、ドンホッジスのパックマンキル画面分析と驚くほど類似していることがわかります

パックマンROMを供給したときにキル画面を忠実に再現しないエミュレーターは、ゲームハードウェアを正しくエミュレートしていないことに注意してください。


「未定義の振る舞い」というフレーズは、1989年以前は印刷物で正確に使用されていなかったかもしれませんが、そのフレーズが記述するという考えはプログラミング自体と同じくらい古いものです。 Common Lisp:言語(Digital Press、1984; ISBN 0-932376-41-X)は、「それはエラーです」という言葉を使用して、まったく同じことを意味していました。例えば、「この関数をx <0で呼び出すのはエラーです」ということは、プログラマーがx <0で関数を呼び出すことを許可してはならず、実装者が文字通り、アプリケーションプログラマは準拠しませんでした。
ソロモンスロー

5
@jameslargeあなたの言いたいことは理解していますが、このコンセプトをパックマンに適用するのは間違いだと思います。ゲームがデザイナーの意図したとおりに動作しないのは明らかであるため、キル画面はバグと言えます。ゲームが未定義の動作を引き起こしたと言うことはできません。なぜなら、Xの値に対して「どんな状況でもプログラマーがXを実行することはできない」と言う言語仕様がないからです。多くのアーケードゲームそれらを使用し、それらすべてが予測可能な効果を持っていることを知っています。)
zwol

1
これが最良の答えです。「未定義の動作」とは、コーダーが、標準に基づいて結果を予測できないコードを記述したことを意味します。PacmanがZ80アセンブリで書かれている場合(そうだと思う)、書かれたコードは、プログラムがコーダーが意図しないことをしたかどうかに関係なく、完全に定義された意味を持ちました。
ロボット

8

プログラムでパックマンの結果では、レベル256のバグ読み取り意図テーブルの終わりを超えていますが、あるデータはまだ読み取り可能な記憶、およびプログラムが書き込もうとするものを超えて、画面の一部に書き込みをされますが、プログラムが書くことが許されている画面の領域の中でまだよく。他のメモリ領域は影響を受けません。

バグがゲームをプレイ不能にする理由は、マシンがプレイヤーが画面の内容を調べることでドットを食べているかどうかを判断し、プレイヤーが244ドットを食べたときにレベルが完了したと判断するためです。画面の一部を上書きすることで、このバグはプレイヤーが244ドットを食べることを不可能にします。その結果、ゲームはプレイヤーにレベルの完了を認めず、画面にドットを再ロードします。


1
レベル256で自殺すると、ドットは再出現しますが、失われることはありません。
アベニュー

@ardaozkal:レベル描画ルーチンは100以上のドットを消去し、いくつかを描画します。プレイヤーのライフが十分であれば、最終的にレベルを上げるのに十分なドットを食べることが可能になりますが、それには30以上のライフが必要です。
スーパーキャット

プレーヤーの生活が十分で、彼がそれを管理したビデオを見たのを覚えています...そして私はそれを見つけました
アベニュー

@ardaozkal:レベルをクリアするのに何人の命が必要ですか、そしてプレイヤーが何人の命を改造されていないマシンに乗せることができますか?
-supercat

変更されていないマシンではレベル256に到達することさえできません。
アベニュー

1

前に言ったように、それはセグの故障ではありません。問題が発生する理由を追加します。オーバーフローです。

レベル番号は1バイトに格納されるため、範囲は0〜255です。レベルを完了するたびに、カウンターが増加します。レベル256では、オーバーフローのため、カウンターは実際には0です。

ただし、ゲームはレベルの下部にいくつかの果物を表示しようとします。果物の数/種類はレベルによって異なります。数式は、レベル8の下の完成したレベルごとに1つの果物を表示します。カウンターによると、レベル0なので、8の下にあります。これは不可能で、このグリッチされた画面を提供します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.