Ответ 1
Обратите внимание на то, как значение 195 соответствует инструкции ret
(возврат из функции) на совместимости 8086. Таким образом, это определение main
ведет себя так, как если бы вы определили его как int main() {}
при выполнении.
На некоторых платформах данные const
загружаются в исполняемую, но не записываемую область памяти, тогда как изменяемые данные (т.е. данные без квалификации const
) загружаются в область записи, но не в исполняемую область памяти. По этой причине программа "работает", когда вы объявляете main
как const
, но не тогда, когда вы опускаете квалификатор const
.
Традиционно двоичные файлы содержали три сегмента:
- Сегмент
text
(если поддерживается архитектурой) защищен от записи и исполняемый файл и содержит исполняемый код, переменные статической продолжительности хранения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
и без параметров (...) или с двумя параметрами (...) или эквивалентным; или каким-либо другим способом реализации.