Обратите внимание, как значение 195 соответствует инструкции ret
(возврат из функции) на устройствах, совместимых с 8086. Таким образом, это определение main
ведет себя так, как если бы вы определили его как int main() {}
при выполнении.
На некоторых платформах данные const
загружаются в исполняемую, но не доступную для записи область памяти, тогда как изменяемые данные (т. Е. Данные, не определенные const
) загружаются в доступную для записи, но не исполняемую область памяти. По этой причине программа «работает», когда вы объявляете main
как const
, но не когда вы опускаете квалификатор const
.
Традиционно двоичные файлы содержали три сегмента:
- Сегмент
text
является (если поддерживается архитектурой) защищенным от записи и исполняемым и содержит исполняемый код, переменные static продолжительности хранения, определенные const
, и строковые литералы
- Сегмент
data
доступен для записи и не может быть выполнен. Он содержит переменные, не квалифицированные const
, с статической продолжительностью хранения и (во время выполнения) объекты с выделенной продолжительностью хранения.
- Сегмент
bss
аналогичен сегменту data
, но инициализируется всеми нулями. Он содержит переменные с статическим сроком хранения, не определенным const
, которые были объявлены без инициализатора.
- Сегмент
stack
отсутствует в двоичном файле и содержит переменные с автоматическим сроком хранения.
Удаление квалификатора const
из переменной main
приводит к его перемещению из сегмента text
в сегмент data
, который не является исполняемым, что вызывает наблюдаемое вами нарушение сегментации.
Современные платформы часто имеют дополнительные сегменты (например, сегмент rodata
для данных, которые не являются ни записываемыми, ни исполняемыми), поэтому, пожалуйста, не воспринимайте это как точное описание вашей платформы, не ознакомившись с документацией по конкретной платформе.
Пожалуйста, поймите, что отказ от main
функции обычно неверен, хотя технически платформа может позволить объявить main
как переменную, см. ISO 9899: 2011 §5.1.2.2.1 ¶1, акцент мой:
1 Функция, вызываемая при запуске программы, называется main
. Реализация не объявляет прототип для этой функции. Он должен быть определен с типом возвращаемого значения int
и без параметров (...) или с двумя параметрами (...) или эквивалентными; или каким-либо другим способом, определяемым реализацией.
person
fuz
schedule
23.10.2015
ret
(возврат из функции) на 8086 и его преемниках. Вы можете догадаться, что происходит, когда вы помещаете это в переменную и вызываете эту переменную как функцию. - person fuz   schedule 23.10.2015ret
инструкцией? - person Ruslan   schedule 24.10.2015