Usiłuję wyjaśnić komuś błędy segmentacji i zastanawiałem się nad ekranem zabijania na poziomie 256 w Pacmanie, jak jest on wywoływany przez przepełnienie liczb całkowitych i jak podobne jest zachowanie do „nieznanego stanu” często opisywanego w segmentacji wina.
Chcę powiedzieć, że jest to dobry przykład tego, co nazywam „nieobsługiwanym segfaultem”, ale wolę uzyskać drugą opinię, zanim potencjalnie rozpowszechnię dezinformację.
Próbowałem to sprawdzić, ale dostaję tylko dokumenty o samym błędzie, a także o współpracy między Hipster Whale a Namco.
Czy zatem uważasz zachowanie na poziomie 256 Pacmana za przykład nieobsługiwanego naruszenia segmentacji?
Odpowiedzi:
Absolutnie nie.
Uzyskiwanie dostępu do adresu pamięci, który nie został przydzielony, jest zawsze błędem programowania. A działanie w oparciu o informacje, które z nich otrzymujesz, powoduje nieokreślone zachowanie, które jest dokładne. Nie mam pojęcia, dla jakiej platformy został napisany oryginalny Pac-man, ale jestem prawie pewien, że wykazywał takie zachowanie, jak każda inna maszyna von Neumanna.
„Błąd segmentacji” jest jednak terminem technicznym na znacznie bardziej szczegółowy warunek. Dzieje się tak, gdy komputer automatycznie wykrywa, że tak się stało, i kończy proces, a nie zezwala na wystąpienie niezdefiniowanego zachowania. Wymaga to określonego (segmentowanego) modelu pamięci z wyrafinowanym tagowaniem własności. Nie sądzę, 1980 gry zręcznościowe, które miałem, aw rzeczywistości zachowanie gry sugeruje, że błąd był nie wykryte, a niezdefiniowane zachowanie nie występuje.
źródło
Wygląda na to, że mylisz „niezdefiniowane zachowanie” i „błąd segmentacji”.
Nie ma czegoś takiego jak nieobsługiwany błąd. Błąd segmentacji to z definicji obsługa błędów.
Jeśli nie masz systemu operacyjnego, który wykrył zły dostęp do pamięci i zakończył proces dla bezpieczeństwa, oznacza to, że nie występuje błąd segmentacji.
Jeśli tak, to jest to całkiem dobry przykład tego, że UB nie zawsze powoduje awarię.
źródło
Żaden z tych terminów nie jest odpowiedni dla błędu w grze zręcznościowej, która została zaprogramowana w języku asemblera i działa bez korzyści sprzętu chroniącego pamięć lub systemu operacyjnego.
„Niezdefiniowane zachowanie” to termin w języku C i językach pokrewnych, ukuty przez komitet normalizacyjny C w 1989 roku. Kod zachowuje się w sposób niezdefiniowany, gdy specyfikacja języka nie określa, co będzie robić. W języku asemblera Z80 nie ma czegoś takiego: efekt każdego kodu operacyjnego przy każdym możliwym wejściu jest dobrze zdefiniowany. Konwencjonalne angielskie znaczenie „niezdefiniowanego zachowania” można odczytać w celu zastosowania - ekran zabójstwa to zachowanie nie zdefiniowane przez ludzi, którzy napisali grę - ale nie użyłbym tego w tym kontekście, ponieważ jest zbyt prawdopodobne, aby podać zły wrażenie.
„Błąd segmentacji” jest terminem w POSIX, wywodzącym się ostatecznie z żargonu programistycznego systemu PDP. Błędy segmentacji występują, gdy program próbuje uzyskać dostęp do adresu pamięci, który nie jest „zmapowany” na nic: sprzęt i system operacyjny wykrywają to i zamykają nieprawidłowo działający program, w dokładnie określony sposób, który umożliwia programowi odzyskanie . Coś jakmogło się to zdarzyć w wyniku błędu w programie do gry Pac-Man, ponieważ płytka drukowana Pac-Man zapełnia pamięć ROM, RAM i urządzenia peryferyjne tylko nieco mniej niż połowę przestrzeni adresowej 64 kB Z80, ale nie mam byłem w stanie dowiedzieć się, co zrobiłby prawdziwy sprzęt, gdyby oprogramowanie próbowało uzyskać dostęp do niezapisanej pamięci. Cokolwiek by to jednak zrobiło, niewłaściwe byłoby opisanie go jako „błąd segmentacji”, ponieważ „system operacyjny” dla Pac-Mana (o ile go ma ) nie jest implementacją Uniksa i, znowu dałoby złe wrażenie.
Tymczasem błąd poziomu 256 nie ma dostępu do niezapisanej pamięci, więc jest dyskusyjny.
Trafne jest stwierdzenie, że w grze występuje błąd, który objawia się po przejściu na poziom 256. Trafne jest również stwierdzenie, że główną przyczyną błędu jest przepełnienie liczb całkowitych , a jego konsekwencjami jest uszkodzenie pamięci (lub, równoważnie, naruszenia) z pamięcią i bezpieczeństwa typu ). Są to wszystkie terminy CS ogólnego przeznaczenia zdefiniowane bez odniesienia do konkretnego języka lub środowiska systemu operacyjnego.
Dokładne jest również zaobserwowanie, że skutki błędu są podobne do skutków błędów w uszkodzeniu pamięci, które nie powodują błędów segmentacji we współczesnym środowisku . Jeśli przeczytasz którykolwiek z opisów exploitów Project Zero , zobaczysz niezwykłe podobieństwo do analizy Dona Hodgesa na ekranie zabicia Pac-Mana .
Zauważ, że emulator, który nie odtwarza wiernie ekranu zabicia po zasileniu ROM-ów Pac-Mana, nie emuluje poprawnie sprzętu gry.
źródło
Błąd poziomu 256 w Pac Man powoduje, że program odczytuje dane, które znajdują się poza końcem planowanej tabeli, ale nadal są czytelne , i zapisują fragmenty ekranu, które wykraczają poza te, które program zamierza zapisać, ale są wciąż dobrze w obszarach ekranu, które program może pisać . Nie ma to wpływu na żadne inne obszary pamięci.
Powodem, dla którego błąd uniemożliwia grę, jest to, że maszyna określa, kiedy gracz je kropki, badając zawartość ekranu i decyduje, że poziom jest ukończony, gdy gracz zje 244 kropki. Nadpisując część ekranu, błąd uniemożliwia graczowi zjedzenie 244 kropek; w związku z tym gra nigdy nie przyzna graczowi ukończenia poziomu i przeładuje ekran kropkami.
źródło
Jak powiedziano wcześniej nie, to nie jest wina seg. Dodam, dlaczego występuje problem: to przepełnienie .
Numer poziomu jest zapisywany w bajcie, więc zakres wynosi 0-255. Za każdym razem, gdy ukończysz poziom, licznik jest zwiększany. Na poziomie 256 licznik jest w rzeczywistości 0 z powodu przepełnienia.
Jednak gra próbuje wyświetlić niektóre owoce na dole poziomu. Liczba / rodzaj owoców zależy od poziomu. Ta formuła wyświetla jeden owoc na ukończonym poziomie poniżej poziomu 8. Według licznika jesteś na poziomie 0, a więc poniżej 8. Test jest wtedy prawdą i musisz wydrukować 255 owoców (stara wartość poziomu). Co jest niemożliwe i daje ten zepsuty ekran.
źródło