在C中没有main()的情况下编译并运行程序
我试图在C
没有main()
函数的情况下编译和运行下面的程序。 我使用以下命令编译了我的程序。
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
,一切都很好。 但是,一旦函数返回,它将尝试跳入调用堆栈中的地址,该地址未被填充。 这是非法访问,并出现分段错误。
一个快速的解决方案是在你的程序结束时调用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);
}
事实上,现在你的函数的行为与常规的main
函数非常相似,因为从main
函数返回后, exit
函数被main
的返回值调用。
在C中,当调用函数/子例程时,堆栈被填充为(按顺序):
main()作为开始点,ELF以这样的方式构造程序,无论先发出哪个指令,都将首先被推送,在这种情况下,printfs是。
现在,程序被截断了,没有返回地址或__end__
,事实上它假定堆栈中的任何地方( __end__
)位置都是返回地址,但不幸的是它不是,因此它崩溃了。
上一篇: Compile and run program without main() in C
下一篇: At what point in the loop does integer overflow become undefined behavior?