在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__ )位置都是返回地址,但不幸的是它不是,因此它崩溃了。

    链接地址: http://www.djcxy.com/p/14027.html

    上一篇: Compile and run program without main() in C

    下一篇: At what point in the loop does integer overflow become undefined behavior?