2013-02-26 13 views
7

Jakie jest zachowanie wywoływania wskaźnika funkcji pustej?NULL wskaźniki funkcji

void (*pFunc)(void) = NULL; 
pFunc(); 

Dlaczego warto zainicjować jeszcze nieużywane wskaźniki funkcji jako NULL?

+1

Tak jak normalny wskaźnik, myślę, że dostaniesz segfault. – Rerito

+1

http://stackoverflow.com/questions/10014284/what-does-null-function-pointer-in-c-mean – Suri

+1

Te dwa pytania odnoszą się do tego samego pytania :-) –

Odpowiedz

7

w C i C++, jest to tzw undefined behaviour, co oznacza, że ​​może to doprowadzić do uszkodzenia segmentacji, nic lub cokolwiek taki przypadek spowoduje że na podstawie Twój kompilator, system operacyjny, na którym uruchamiasz ten kod, środowisko (itp.) oznacza.

Inicjowanie wskaźnika do funkcji lub ogólnie wskaźnika na wartość NULL pomaga niektórym programistom upewnić się, że ich wskaźnik nie został zainicjowany i nie jest równy wartości losowej, co zapobiega przypadkowemu usunięciu odwołania.

+0

Gdyby było dobrze, gdyby SEGFAULT był gwarantowany . – Vorac

+1

Spowoduje to usterkę segmentacji w 99% przypadków i na wielu systemach/architekturach. Standard nie stwierdza jednak jednoznacznie, że tak się stanie. –

+0

Myślę, że jest to zachowanie "nieokreślone", ale naprawdę nieokreślone. Co się stanie, jeśli pamięć 0x0 będzie adresowalna i "wykonywalna" ... –

0

Jest to wskazane z tego samego powodu, co inicjalizacja "normalnych" wskaźników (danych) do NULL: ponieważ potencjalnie ułatwia wykrycie niektórych błędów. Opinie na temat tego, czy jest to przydatne lub nie różnią się oczywiście :-)

1
  1. Co się dzieje, gdy próbujesz uzyskać dostęp NULL? Poniższa komenda dotyczy zarówno danych, jak i kodu, i to jest to, co stanie się podczas próby odczytania wartości NULL (lub dowolnego adresu od 0 do 4096, tj. Co najmniej pierwszej strony segmentu). Przyczyną tego jest OS i mikroprocesor segmentacja/stronicowania architektury

    Podczas próby dostępu NULL (lub 0), adres, w każdym z danych lub kod sekcji powoduje winy segmentacji (co jest rzeczywiście mordercą błąd strony). Pierwsza strona sekcji jest traktowana jako część (lub nieważna część wirtualna) z (lub nieważna część ). Celowe jest to, że pierwsza strona jest niepoprawna (lub nieobecna), więc co najmniej jeden adres, który zawiera wskaźnik , może być reprezentowany jako niepoprawny w czasie wykonywania programu w czasie wykonywania .

    Deskryptor strony pierwszej strony (która zawiera adres wirtualny 0, NULL), ma pierwszy bit "obecny" jako 0 (oznacza jego nieprawidłową stronę). Teraz, jeśli spróbujesz uzyskać dostęp do wskaźnika NULL (adres 0), spowoduje to błąd strony na stronie , ponieważ strona nie istnieje, a system operacyjny spróbuje obsłużyć tę stronę o błędzie . Gdy program obsługi błędów strony zobaczy, że próbuje uzyskać dostęp do pierwszej strony , która jest traktowana jako niepoprawna część adresu wirtualnego , zabija proces. Wszystko zależy od procesu przestrzeni użytkownika. Jeśli spróbujesz uzyskać dostęp do wskaźnika NULL w procesie systemowym (kod poziomu jądra), , to zawiedzie system operacyjny.

    Linki: http://en.wikipedia.org/wiki/Page_fault#Invalid http://en.wikipedia.org/wiki/Memory_protection#Paged_virtual_memory http://pdos.csail.mit.edu/6.828/2005/readings/i386/s05_02.htm

    Powyżej jest wystarczająca bt jak myślę, że u należy przeczytać również http://www.iecc.com/linker/linker04.txt

  2. Dlaczego wskaźnik funkcja jest zerowane? Mimo to, jeśli spróbujesz wywołać funkcję NULL, spowoduje to błąd strony/segmentu. NULL oznacza jego nieprawidłową funkcję.Jeśli to zawiera dowolny adres śmieci, ale w poprawnej wirtualnej przestrzeni adresowej sekcji kodu , myślę, że zostanie wywołany dowolny kod pod tym adresem, który może być jeszcze bardziej katastrofalny (spl w przypadku systemów czasu rzeczywistego). Initialize funcp = funct_foo_name + 1; teraz wywołaj funkcję za pomocą wskaźnika funkcji . Wskaźnik funkcji wskazuje na prawidłowy adres wirtualny przestrzeń sekcji kodu. Funkcja bt uruchomi się z niewłaściwego miejsca, aby wykonać . co może spowodować błędne wykonanie kodu lub błędne zamówienie.

+1

Tworzysz zbyt wiele założeń, które niekoniecznie muszą istnieć. Pracowałem na platformach, na których adres 0 nie jest traktowany inaczej niż adres 42890. –

+1

Uczymy nas [Dziesięć przykazań] (http://www.lysator.liu.se/c/ten-commandments.html), "Nie podążaj za wskaźnikiem NULL, bo chaos i szaleństwo czekają na ciebie na końcu". – vonbrand

+0

@NikBougalis: Jesteś prawdą. To, co rozumiem przez pierwszą stronę lub nieprawidłowy zakres adresów od 0 do 4096 (co jest standardowym rozmiarem strony x386), to nieważna wirtualna przestrzeń adresowa. Ponieważ uważam, że jest to zależne od systemu operacyjnego, ile początkowej części zakresu przestrzeni adresowej wirtualnej uważa za nieprawidłowe –

Powiązane problemy