我很惊讶为什么这有效?
short main [] ={};
这是文件中唯一的内容。它在 gcc 上正确编译。但是当我运行它时会打印分段错误。当我重命名 main 时,编译器会出错。谁能解释一下这里发生了什么。
我很惊讶为什么这有效?
short main [] ={};
这是文件中唯一的内容。它在 gcc 上正确编译。但是当我运行它时会打印分段错误。当我重命名 main 时,编译器会出错。谁能解释一下这里发生了什么。
显然链接器不知道全局对象的类型(例如:变量或函数),而只知道地址;因此它将程序链接起来,就好像您的变量是一个函数一样。由于明显的原因而崩溃。
你有这样的错误吗?
Undefined symbols:
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
这不是编译器错误,而是链接器错误。
在编译中,每个源文件都被翻译成一个目标文件。
没有检查是否int main()
存在,因为程序可能包含多个源,并且main()
仅在其中一个中定义,或者它甚至不需要存在(例如在动态库中)。由于源
short main[] = {};
被编译器认为是一个有效的声明(创建一个short
名为的全局数组main
并初始化为一个空数组),它不会产生任何错误。
是否int main()
存在的检测由链接器检查。链接器将编译的目标文件绑定到一个工作的可执行文件。如果链接器找不到符号main
,它会像我上面描述的那样抱怨。不幸的是,传统的 C ABI 不区分函数或导出变量的种类。所以即使main
被声明为一个数组,因为链接器只知道“main
存在的东西”并且不能检查更多,它也会通过。
结果是尽管写错了程序,但生成的程序没有错误。
当程序运行时,所谓main
不持有可执行代码。相反,它只是一些数据(可能归零)。所以系统可能会做任何意想不到的事情(在你的情况下,它是一个 SEGFAULT)。
这实际上可以在使用-Wall
gcc 中的标志编译时被捕获,这会给出警告:
<stdin>:1: warning: ‘main’ is usually a function
尝试使用更多选项进行编译。:)
例如添加简单的 -Wall
gcc -Wall test.c -o t
test.c:1: warning: ‘main’ is usually a function
我没有阅读相关的标准页面,但显然你只需要拥有某种 main 才能编译,不一定是函数......