在C语言中编译并运行没有main()的程序
我试图编译和运行下面的程序没有main()
函数在C
。 我已经使用以下命令编译了我的程序。
gcc -nostartfiles nomain.c
编译器给出警告
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400340
好吧,没问题。 然后,我运行可执行文件(a.out), printf
语句都成功打印,然后出现分段错误 。
所以,我的问题是, 成功执行打印语句后为什么分段错误?
我的代码:
#include <stdio.h> void nomain() { printf("Hello World...\n"); printf("Successfully run without main...\n"); }
输出:
Hello World... Successfully run without main... Segmentation fault (core dumped)
注意:
在这里, -nostartfiles
gcc标志防止编译器在链接时使用标准启动文件
让我们来看看你的程序生成的程序集:
.LC0: .string "Hello World..." .LC1: .string "Successfully run without main..." nomain: push rbp mov rbp, rsp mov edi, OFFSET FLAT:.LC0 call puts mov edi, OFFSET FLAT:.LC1 call puts nop pop rbp ret
注意ret
语句。 您的程序入口点被确定为不是nomain
,一切都很好。 但是,一旦函数返回,它将尝试跳转到未被填充的调用堆栈中的地址。 这是一个非法的访问和分段错误如下。
一个快速的解决scheme是在你的程序结束时调用exit
(假设C11我们可能把_Noreturn
标记为函数):
#include <stdio.h> #include <stdlib.h> _Noreturn void nomain(void) { printf("Hello World...\n"); printf("Successfully run without main...\n"); exit(0); }
实际上,现在你的函数performance得像一个常规的main函数,因为从main返回后,exit函数被调用main的返回值。
在C中,当调用函数/子程序时,堆栈被填充为(按顺序):
- 论点,
- 退货地址,
- 局部variables, – > 栈顶
main()作为开始点,ELF以这样的方式构造程序,无论指令先到哪里,都会先被推送,在这种情况下,printfs是。
现在,程序被截断了,没有返回地址或者__end__
,事实上它假定堆栈中的任何东西( __end__
)都是返回地址,但不幸的是它不是,所以它崩溃了。