我从同事那里学到,可以在不写main()
函数的情况下编写和执行C程序。做法如下:
my_main.c
/* Compile this with gcc -nostartfiles */
#include <stdlib.h>
void _start() {
int ret = my_main();
exit(ret);
}
int my_main() {
puts("This is a program without a main() function!");
return 0;
}
使用以下命令编译:
gcc -o my_main my_main.c –nostartfiles
使用以下命令运行:
./my_main
何时需要做这种事?是否有任何真实世界的场景会用到这个功能?
_start()
和其他在main()
之外的东西的一些细节,非常值得一读。 - user439793_start
或除了main
之外的任何入口点都没有明确规定(除了对于自由站(嵌入式)实现,入口点的名称是实现定义的)。 - Keith Thompson_start
不安全,调用my_main
时违反了 ABI;您告诉编译器它是一个普通函数,但实际上它已经使用堆栈指针对齐(例如,在 x86-64 上,RSP%16 == 0),而不是 RSP%16 == 8,就像在调用推送 8 字节返回地址的普通函数之后进入一样。 您可以通过为_start
使用__attribute__((force_align_arg_pointer))
来解决这个问题,告诉 GCC 在进入该“函数”时堆栈指针可能会“错位”,如 Get arg values with inline asm without Glibc? 中所示。 - Peter Cordesmy_main
使用scanf或printf(或任何可变参数函数)带有float
或double
FP参数,这将导致崩溃。当从不对齐RSP的函数调用glibc scanf时会出现分段错误。 - Peter Cordes