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

标签 c gcc segmentation-fault program-entry-point gcc-warning

我正在尝试在 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/

相关文章:

c - 32 副牌的具体排列(C 语言)

gcc 忽略 -Wl,--dynamic-linker 开关

c - 段错误检查 strcmp

linux - 如何在 Linux 中处理多个 SIGSEGV 事件?

ruby - 让 Ruby 识别子进程是否出现段错误

c - 等待单个对象 : do not lock a mutex but check the current state?

c++ - 从 Linux 中的多个非阻塞命名管道读取

代码在 GCC 上编译正常,但在 VC2010 上有很多错误

c - 我们如何使用 fgetpos() 来获取文件的大小

c - 即使使用 -g 选项,GCC 也不会生成行号信息