2013-03-11 10 views
29

На какое-то мгновение я очень гордился тем, что написал свою, вероятно, первую программу C без ошибок. Вот весь исходный код:Самая короткая программа на C, все еще вызывает segfault

int main; 

Он компилирует прекрасно даже без int, но выдается предупреждение (даже без -Wall) и, как программист, который метит в программе свободное от ошибок, я лечу их как ошибки.

С радостью скомпилировав это приложение, я сразу же бросился его запускать. К моему удивлению, возникла ошибка сбоя сегментации ...


Теперь серьезно. Что именно происходит?

Моя догадка заключается в следующем: это отсутствие определения main. Это так очевидно, но компилятор разрешает это. OK, main могут быть определены в другом блоке. Но даже компоновщик ничего не делает по этому поводу. Любая конкретная причина?

+0

Я думаю, что проблема в том, что вы просто определить прототип, но не саму функцию, но ждать: Вы просто определить переменную и никакие функции. Пока точка входа не определена. – rekire

+7

Это [пояснение по Reddit] (http://www.reddit.com/r/programming/comments/19xyw1/some_dark_corners_of_c_presentation/c8swcpi?context=2) может помочь. – DCoder

+0

Это зависит от того, как и где вы компилируете свою программу. Для программ с размещенной средой требуется «основная», но автономные программы для среды нет. –

ответ

20

Слово main является юридическим именем для любой переменной. Типичным вариантом использования является предоставление функции имени main компилятору, который компилирует его в файл объекта, который, в свою очередь, связан с crt0.o, который обеспечивает инициализацию для времени выполнения (распределение стека и т. Д.) И переходы на ярлык main.

В объектных файлах C символы не связаны с прототипами, и компоновщику удается привязать глобальную переменную int main; к главной программе, к которой нужно подпрыгнуть. Однако эта программа является мусором. Скорее всего, он инициализируется как нули, но вскоре процессор встречает либо случайную инструкцию, которая обращается к памяти за пределами распределенного пространства программ (стек + куча), либо поток команд достигает пределов зарезервированного кодового пространства.

Оба будут вызывать ошибку сегментации. И на самом деле, если система работает на архитектуре с флагами eXecution, программа segfaults при первой попытке перейти на данные сегмент или страница без разрешения на выполнение.

Дальнейшее чтение, чтобы поддержать дискуссию в комментариях: Data Execute Prevention, NX_bit

+0

В эпоху MS-DOS я полагаю, что можно было написать рабочий 'char main = 0xc3;' –

+4

try 'const char main = 0xc3;' – moooeeeep

+0

Право или даже 'const main = 195;' –

Смежные вопросы