繁体   English   中英

在C中不使用main()编译并运行程序

[英]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语言中,当调用函数/子例程时,堆栈填充为(按顺序):

  1. 论据
  2. 退货地址,
  3. 局部变量-> 堆栈顶部

main()是起点,ELF构造程序的方式是,首先执行的任何指令都将首先被推送,在这种情况下,printfs会被推送。

现在,程序被截断了一些,没有返回地址或__end__ ,实际上它假定那个( __end__ )位置的堆栈上的任何内容都是返回地址,但不幸的是它没有,因此崩溃了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM