Nulový ukazatel - Null pointer

Při práci na počítači je nulový ukazatel nebo nulový odkaz hodnota uložená pro označení, že ukazatel nebo odkaz neodkazuje na platný objekt . Programy běžně používají nulové ukazatele k vyjádření podmínek, jako je konec seznamu neznámé délky nebo neprovedení nějaké akce; toto použití nulových ukazatelů lze porovnat s typy s možnou hodnotou null a s hodnotou Nic v typu možnosti .

Nulový ukazatel by neměl být zaměňován s neinicializovaným ukazatelem : nulový ukazatel je zaručen pro porovnání nerovné s jakýmkoli ukazatelem, který ukazuje na platný objekt. V závislosti na jazyce a implementaci však neinicializovaný ukazatel nemusí mít žádnou takovou záruku. Mohlo by se to rovnat jiným platným ukazatelům; nebo to může být srovnatelné s nulovými ukazateli. Může to dělat obojí v různých časech; nebo srovnání může být nedefinované chování .

C

V C jsou dva nulové ukazatele jakéhokoli typu zaručeně porovnatelné. Makro preprocesoru NULLje definováno jako implementačně definovaná nulová konstanta ukazatele, kterou lze v C99 přenosně vyjádřit jako celočíselnou hodnotu 0převedenou na typ void*(ukazatel na neplatnost ). Standard C neříká, že nulový ukazatel je stejný jako ukazatel na adresu paměti  0, i když v praxi to tak může být. Dereferencování nulového ukazatele je nedefinované chování v jazyce C a odpovídající implementace může předpokládat, že jakýkoli ukazatel, který je dereferencovaný, není null.

V praxi může dereferencování nulového ukazatele vést k pokusu o čtení nebo zápis z paměti, která není mapována, což způsobí chybu segmentace nebo narušení přístupu k paměti. To se může projevit jako selhání programu nebo může být transformováno na softwarovou výjimku, kterou může zachytit kód programu. Existují však určité okolnosti, kdy tomu tak není. Například v reálném režimu x86 je adresa čitelná a také obvykle zapisovatelná a odkázání ukazatele na tuto adresu je naprosto platná, ale obvykle nežádoucí akce, která může vést k nedefinovanému, ale nepadajícímu chování v aplikaci. Existují případy, kdy dereferencování ukazatele na adresu nula je záměrné a dobře definované; například kód BIOS zapsaný v jazyce C pro 16bitová zařízení x86 v reálném režimu může zapisovat IDT na fyzickou adresu 0 počítače zrušením odkazu na nulový ukazatel pro zápis. Je také možné, aby kompilátor optimalizoval dereferenci nulového ukazatele, aby se vyhnul chybě segmentace, ale způsobil jiné nežádoucí chování . 0000:0000

C ++

V C ++, zatímco NULLmakro bylo zděděno z C, bylo tradičně upřednostňováno celočíselné literál pro nulu, aby představovalo konstantu nulového ukazatele. Nicméně, C ++, 11 zavedl explicitní ukazatel NULL konstanta nullptrmá být použit místo.

Jiné jazyky

V některých prostředích programovacího jazyka (alespoň jedna proprietární implementace Lisp, například) může být hodnota použitá jako nulový ukazatel (nazývaná nilv Lispu ) ve skutečnosti ukazatelem na blok interních dat užitečných pro implementaci (ale není výslovně dosažitelný z uživatelské programy), což umožňuje použít stejný registr jako užitečnou konstantu a rychlý způsob přístupu k interním implementacím. Toto je známé jako nilvektor .

V jazycích s tagovanou architekturou může být případně nulový ukazatel nahrazen tagovaným sjednocením, které vynucuje explicitní zpracování výjimečného případu; ve skutečnosti je možné nulový ukazatel považovat za označený ukazatel s vypočítanou značkou.

Programovací jazyky používají pro nulový ukazatel různé literály . V Pythonu je například volána nulová hodnota None. V Pascalu a Swiftu se nazývá nulový ukazatel nil. V Eiffelovi se tomu říká voidreference.

Nulové dereferencování

Protože nulový ukazatel neukazuje na smysluplný objekt, pokus o dereference (tj. Přístup k datům uloženým na tomto paměťovém místě) nulový ukazatel obvykle (ale ne vždy) způsobí chybu běhu nebo okamžité selhání programu.

  • V C je dereferencování nulového ukazatele nedefinované chování . Mnoho implementací způsobuje, že takový kód má za následek zastavení programu s narušením přístupu , protože reprezentace nulového ukazatele je vybrána jako adresa, kterou systém nikdy nepřiděluje pro ukládání objektů. Toto chování však není univerzální. Není to také zaručeno, protože kompilátorům je povoleno optimalizovat programy za předpokladu, že neobsahují nedefinované chování.
  • V Delphi a mnoha dalších implementacích Pascal nilpředstavuje konstanta nulový ukazatel na první adresu v paměti, která se také používá k inicializaci spravovaných proměnných. Dereferencování vyvolá externí výjimku operačního systému, která je mapována na instanci výjimky Pascal EAccessViolation, pokud je jednotka System.SysUtils propojena v klauzuli uses.
  • V Javě přístup k nulové referenci spouští NullPointerException(NPE), který lze zachytit kódem pro zpracování chyb, ale upřednostňovanou praxí je zajistit, aby se takové výjimky nikdy nevyskytovaly.
  • V .NET přístup k nulové referenci vyvolá vyvolání NullReferenceException. Ačkoli je jejich chytání obecně považováno za špatnou praxi, program tohoto druhu výjimky může být chycen a zpracován.
  • V Objective-C mohou být zprávy odesílány na nilobjekt (což je nulový ukazatel), aniž by došlo k přerušení programu; zpráva je jednoduše ignorována a návratová hodnota (pokud existuje) je nilnebo 0, v závislosti na typu.
  • Před zavedením SMAP by mohla být zneužita chyba dereference nulového ukazatele mapováním pagezero do adresního prostoru útočníka, a proto by nulový ukazatel ukazoval na tuto oblast. V některých případech to může vést ke spuštění kódu .

Zmírnění

Existují techniky, které usnadňují ladění dereferencí nulového ukazatele. Bond a kol. navrhnout upravit JVM, aby bylo možné sledovat nulové šíření. Myšlenkou systému Casper je použít ke sledování této propagace transformaci zdrojového kódu bez úpravy JVM. V některých případech je možné automaticky generovat opravu k opravě výjimek nulového ukazatele.

Dějiny

V roce 2009 Sir Tony Hoare uvedl, že vynalezl nulovou referenci v roce 1965 jako součást jazyka ALGOL W. V té referenci z roku 2009 Hoare popisuje svůj vynález jako „miliardovou chybu“:

Říkám tomu moje miliardová chyba. Byl to vynález nulové reference v roce 1965. V té době jsem navrhoval první komplexní typový systém pro reference v objektově orientovaném jazyce (ALGOL W). Mým cílem bylo zajistit, aby veškeré použití odkazů bylo naprosto bezpečné, přičemž kontrolu provádí automaticky překladač. Ale nemohl jsem odolat pokušení uvést nulovou referenci, jednoduše proto, že bylo tak snadné ji implementovat. To vedlo k nesčetným chybám, zranitelnostem a selháním systému, které za posledních čtyřicet let pravděpodobně způsobily bolest a škody za miliardu dolarů.

Viz také

Reference

Citace

Prameny

  • Smíšená technická komise ISO/IEC JTC 1, podvýbor SC 22, pracovní skupina WG 14 (2007-09-08). Mezinárodní norma ISO/IEC 9899 (PDF) (návrh výboru).Správa CS1: více jmen: seznam autorů ( odkaz )