2013-03-11 10 views
29

Przez chwilę byłem bardzo dumny z tego, że napisałem swój pierwszy prawdopodobnie program bez błędów. Oto cały kod źródłowy:Najkrótszy program w języku C nadal wywołuje usterkę.

int main; 

To kompiluje doskonale nawet bez int, ale jest ostrzeżenie (nawet bez -Wall) i, jako programista, który ma na celu programu wolna od błędów, traktuję jako błędy.

Po pomyślnym skompilowaniu tej aplikacji natychmiast rzuciłem się, aby ją uruchomić. Ku mojemu zaskoczeniu pojawił się błąd błędu segmentacji ...


Poważnie. Co się dokładnie dzieje?

Moje przypuszczenie jest następujące: to brak definicji main. Jest to tak oczywiste, a mimo to pozwala na to kompilator. OK, main można zdefiniować w innej jednostce. Ale nawet linker nic z tym nie robi. Jakiś konkretny powód, dlaczego?

+0

Myślę, że problemem jest to, że wystarczy zdefiniować prototyp, ale nie samą funkcję, ale czekać: wystarczy zdefiniować zmienną i żadnych funkcji. Jak dotąd punkt wejścia nie jest zdefiniowany. – rekire

+7

To [wyjaśnienie na Reddit] (http://www.reddit.com/r/programming/comments/19xyw1/some_dark_corners_of_c_presentation/c8swcpi?context=2) może pomóc. – DCoder

+0

To zależy od tego, jak i gdzie skompilujesz swój program. Hostowane programy środowiskowe wymagają "głównego", ale programy środowiskowe typu "wolnostojące" nie. –

Odpowiedz

20

Słowo main jest prawną nazwą każdej zmiennej. Typowym przypadkiem użycia jest zapewnienie funkcji nazwy kompilatora, która kompiluje ją do pliku obiektowego, który z kolei jest połączony z crt0.o, który zapewnia inicjalizację dla czasu wykonywania (przydział sterty itp.) I przeskakuje do etykieta main.

W plikach obiektowych C symbole nie są powiązane z prototypami, a linkerowi udało się połączyć globalną zmienną int main; jako główny program do przeskoczenia. Ten program jest jednak śmieciem. Najprawdopodobniej zostanie zainicjowany jako zera, ale wkrótce procesor napotka przypadkową instrukcję, która uzyskuje dostęp do pamięci poza przydzielonymi przez program obszarami danych (stos + sterta) lub przepływ instrukcji osiąga ograniczenia zarezerwowanej przestrzeni kodu.

Obie będą powodować błąd segmentacji. I faktycznie, jeśli system działa na architekturze z flagami eXecution, program ulega uszkodzeniu przy pierwszej próbie przeskoczenia do segmentu lub strony danych bez pozwolenia na wykonanie.

Dalsza lektura wspierać dyskusję w komentarzach: Data Execute Prevention, NX_bit

+0

Przypuszczam, że w erze MS-DOS możliwe było napisanie działającego 'char main = 0xc3;' –

+4

spróbuj 'const char main = 0xc3;' – moooeeeep

+0

W prawo, lub nawet 'const main = 195;' –

Powiązane problemy