[英]Compile and run program without main() in C
我正在尝试在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
返回后,将使用main
的返回值调用exit
函数。
在C语言中,当调用函数/子例程时,堆栈填充为(按顺序):
main()是起点,ELF构造程序的方式是,首先执行的任何指令都将首先被推送,在这种情况下,printfs会被推送。
现在,程序被截断了一些,没有返回地址或__end__
,实际上它假定那个( __end__
)位置的堆栈上的任何内容都是返回地址,但不幸的是它没有,因此崩溃了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.