为什么const int main = 195导致一个工作程序,但没有const它会以分段错误结束?

Des*_*tor 32 c program-entry-point const segmentation-fault

考虑使用C程序(请参阅此处的实时演示).

const int main = 195;
Run Code Online (Sandbox Code Playgroud)

我知道在现实世界中没有程序员编写这样的代码,因为它没有任何用处,也没有任何意义.但是当我const从程序上方删除关键字时,它会立即导致分段错误.为什么?我很想知道这背后的原因.

GCC 4.8.2在编译时会发出以下警告.

警告:'main'通常是一个函数[-Wmain]

const int main = 195;
          ^
Run Code Online (Sandbox Code Playgroud)

为什么const关键字的存在和缺失会对程序的行为产生影响?

fuz*_*fuz 60

观察值195如何对应ret于8086兼容机上的(从函数返回)指令.main因此,此定义的行为就像您将其定义为int main() {}执行时一样.

在某些平台上,const数据被加载到可执行但不可写的存储区域中,而可变数据(即未限定的数据const)被加载到可写但不可执行的存储区域中.出于这个原因,该计划"作品"在声明mainconst,当你离开离开,但没有const限定.

传统上,二进制文件包含三个部分:

  • text段(如果受架构支持)写保护和可执行,并包含可执行代码,静态存储持续时间限定的变量const和字符串文字
  • data段是可写的,无法执行.它包含未const使用静态存储持续时间限定的变量和(在运行时)具有已分配存储持续时间的对象
  • bss段与段类似,data但初始化为全零.它包含未使用初始化程序声明的静态 存储持续时间的变量const
  • stack段不存在于二进制文件中,并包含具有自动 存储持续时间的变量

const从变量中删除限定符main会导致它从段移动textdata不可执行的段,从而导致您观察到的段违例.

现代平台通常还有其他段(例如rodata,既不可写也不可执行的数据段),因此请不要在没有咨询平台特定文档的情况下将其作为平台的准确描述.

请理解,不创建main函数通常是不正确的,尽管技术上平台可以允许main声明为变量,参见 ISO 9899:2011§5.1.2.2.11,强调我的:

1命名程序启动时调用的函数main.该实现声明此函数没有原型.它应定义为返回类型int且没有参数(...)或两个参数(...)或等效物; 或者以某种其他实现定义的方式.


Bat*_*eba 11

在C中,main全局范围几乎总是一个函数.

main在全局范围内用作变量,会使程序的行为不确定.

(可能是这样的情况,当您编写const编译器时,将变量优化为常量,因此您的程序行为是不同的.但程序行为仍未定义).

  • 参看 ISO 9899:2011§5.1.2.2.1"程序启动时调用的函数名为main.该实现声明此函数没有原型.它应该用返回类型int定义并且没有参数:( ...)或者有两个参数(这里称为argc和argv,尽管可以使用任何名称,因为它们是函数的本地函数)声明):( ...)或同等的; 10)或以其他一些实现定义的方式." (8认同)
  • 不.平台可以允许"main"以"实现定义的方式"声明. (5认同)