簡體   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