Uczę się języka C ++ i trudno mi zrozumieć zero. W szczególności w samouczkach, które przeczytałem, wspomniano o „zerowym sprawdzaniu”, ale nie jestem pewien, co to oznacza ani dlaczego jest konieczne.
- Czym dokładnie jest zero?
- Co to znaczy „sprawdzić, czy nie ma nic”?
- Czy zawsze muszę sprawdzać, czy nie ma wartości null?
Wszelkie przykłady kodu będą mile widziane.
Odpowiedzi:
W C i C ++ wskaźniki są z natury niebezpieczne, to znaczy, gdy wyrejestrujesz wskaźnik, Twoim obowiązkiem jest upewnienie się, że wskazuje on gdzieś poprawnie; jest to część tego, o co chodzi w „ręcznym zarządzaniu pamięcią” (w przeciwieństwie do automatycznych schematów zarządzania pamięcią zaimplementowanych w językach takich jak Java, PHP lub środowisko uruchomieniowe .NET, które nie pozwalają na tworzenie nieprawidłowych referencji bez znacznego wysiłku).
Częstym rozwiązaniem, które wychwytuje wiele błędów, jest ustawianie wszystkich wskaźników, które nie wskazują na nic jako
NULL
(lub, w poprawnym C ++0
), i sprawdzanie tego przed uzyskaniem dostępu do wskaźnika. W szczególności powszechną praktyką jest inicjowanie wszystkich wskaźników na NULL (chyba że masz już coś, na co można je wskazać, kiedy je deklarujesz) i ustawianie ich na NULL, gdy tydelete
lubfree()
oni (chyba, że natychmiast przestaną być objęte zakresem). Przykład (w C, ale także poprawny C ++):Lepsza wersja:
Bez kontroli zerowej przekazanie wskaźnika NULL do tej funkcji spowoduje awarię segregacji i nic nie możesz zrobić - system operacyjny po prostu zabije Twój proces i być może zrzut pamięci lub wyświetli okno dialogowe raportu o awarii. Po wprowadzeniu kontroli zerowej możesz prawidłowo obsługiwać błędy i odzyskać wdzięczność - samodzielnie rozwiąż problem, przerwij bieżącą operację, napisz wpis w dzienniku, powiadom użytkownika o wszystkim, co jest odpowiednie.
źródło
Pozostałe odpowiedzi w zasadzie dotyczyły twojego dokładnego pytania. Kontrola zerowa ma na celu upewnienie się, że otrzymany wskaźnik wskazuje prawidłową instancję typu (obiekty, operacje podstawowe itp.).
Jednak dodam tutaj swoją własną radę. Unikaj kontroli zerowej. :) Kontrola zerowa (i inne formy programowania defensywnego) zaśmiecają kod i sprawiają, że jest on bardziej podatny na błędy niż inne techniki obsługi błędów.
Moją ulubioną techniką, jeśli chodzi o wskaźniki obiektów, jest użycie wzorca Null Object . Oznacza to, że zwracamy (wskaźnik - lub nawet lepiej, odwołanie do) pustą tablicę lub listę zamiast null, lub zwracamy pusty ciąg („”) zamiast null, a nawet ciąg „0” (lub coś równoważnego „nic” „w kontekście), gdzie oczekuje się, że zostanie on sparsowany do liczby całkowitej.
Jako bonus, oto coś, czego mogłeś nie wiedzieć o wskaźniku zerowym, który został (po raz pierwszy formalnie) zaimplementowany przez CAR Hoare dla języka Algol W w 1965 roku.
źródło
Wartość wskaźnika zerowego reprezentuje dobrze zdefiniowane „nigdzie”; jest to niepoprawna wartość wskaźnika, która gwarantuje porównanie nierówne z dowolną inną wartością wskaźnika. Próba wyrejestrowania wskaźnika zerowego powoduje niezdefiniowane zachowanie i zwykle prowadzi do błędu środowiska wykonawczego, dlatego przed upewnieniem się, że wskaźnik nie ma wartości NULL, należy upewnić się, że wskaźnik nie ma wartości NULL. Szereg funkcji bibliotecznych C i C ++ zwróci wskaźnik zerowy wskazujący warunek błędu. Na przykład funkcja biblioteczna
malloc
zwróci wartość wskaźnika zerowego, jeśli nie będzie mogła przydzielić żądanej liczby bajtów, a próba uzyskania dostępu do pamięci przez ten wskaźnik (zwykle) doprowadzi do błędu w czasie wykonywania:Musimy więc upewnić się, że
malloc
wywołanie zakończyło się powodzeniem, sprawdzając wartośćp
przeciw NULL:A teraz poczekaj chwilę na skarpetkach, to będzie trochę wyboiste.
Istnieje wskaźnik NULL wartość i null pointer stałe , a dwa nie zawsze są takie same. Null pointer wartość jest niezależnie od wartości leżących u podstaw architektury zastosowania do reprezentowania „nigdzie”. Ta wartość może wynosić 0x00000000 lub 0xFFFFFFFF, 0xDEADBEEF lub coś zupełnie innego. Nie należy zakładać, że wskaźnik zerowa wartość jest zawsze 0.
Stała wskaźnika zerowego , OTOH, jest zawsze wyrażeniem całkowitym o wartości 0. Jeśli chodzi o kod źródłowy , 0 (lub dowolne wyrażenie całkowite, którego wynikiem jest 0), oznacza wskaźnik zerowy. Zarówno C, jak i C ++ definiują makro NULL jako stałą wskaźnika zerowego. Gdy kod zostanie skompilowany, null pointer stałe zostaną zastąpione odpowiednim zerowy wskaźnik wartości w wygenerowanego kodu maszynowego.
Pamiętaj również, że NULL jest tylko jedną z wielu możliwych nieprawidłowych wartości wskaźnika; jeśli zadeklarujesz zmienną wskaźnika automatycznego bez jawnej jej inicjalizacji, np
wartość początkowo przechowywana w zmiennej jest nieokreślona i może nie odpowiadać prawidłowemu lub dostępnemu adresowi pamięci. Niestety, nie ma (przenośnego) sposobu, aby stwierdzić, czy wartość wskaźnika inna niż NULL jest poprawna, czy nie przed próbą jej użycia. Więc jeśli masz do czynienia ze wskaźnikami, zwykle dobrym pomysłem jest jawne zainicjowanie ich na NULL, kiedy je deklarujesz, i ustawienie ich na NULL, gdy nie wskazują na nic aktywnie.
Zauważ, że jest to bardziej problem w C niż w C ++; idiomatic C ++ nie powinien zbyt często używać wskaźników.
źródło
Istnieje kilka metod, wszystkie w zasadzie robią to samo.
kontrola zerowa (sprawdź, czy wskaźnik jest pusty), wersja A
kontrola zerowa, wersja B
kontrola zerowa, wersja C
Z tych trzech wolę użyć pierwszego czeku, ponieważ wyraźnie mówi przyszłym programistom, co próbujesz sprawdzić ORAZ wyjaśnia, że spodziewałeś się, że foo będzie wskaźnikiem.
źródło
Ty nie. Jedynym powodem użycia wskaźnika w C ++ jest to, że jawnie chcesz obecność wskaźników zerowych; w przeciwnym razie możesz wziąć odwołanie, które jest semantycznie łatwiejsze w użyciu i gwarantuje wartość inną niż null.
źródło
export
) oraz wszystkie funkcje biblioteki C ++ 03 oraz TR1 i sporą część C ++ 11.Jeśli nie sprawdzasz wartości NULL, szczególnie jeśli jest to wskaźnik do struktury, być może napotkałeś lukę w zabezpieczeniach - dereferencję wskaźnika NULL. Dereferencja wskaźnika NULL może prowadzić do innych poważnych luk w zabezpieczeniach, takich jak przepełnienie bufora, warunki wyścigu ... które mogą pozwolić atakującemu przejąć kontrolę nad twoim komputerem.
Wielu dostawców oprogramowania, takich jak Microsoft, Oracle, Adobe, Apple ... wydaje poprawki oprogramowania, aby naprawić te luki w zabezpieczeniach. Myślę, że powinieneś sprawdzić NULL wartość każdego wskaźnika :)
źródło