我正在尝试在 C
中编译并运行以下没有 main()
函数的程序。我使用以下命令编译了我的程序。
gcc -nostartfiles nomain.c
编译器给出警告
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400340
好的,没问题。然后,我运行了可执行文件 (a.out),两个 printf
语句都成功打印,然后得到 segmentation fault。
所以,我的问题是,为什么在成功执行打印语句后出现段错误?
我的代码:
#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标志阻止编译器在链接时使用标准启动文件
最佳答案
让我们看看生成的assembly你的程序:
.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() 编译和运行程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42328165/