linux下gcc In function `_start'


沒有main函數,,
我們常用gcc main.c -o main命令編譯一個程序,
其實也可以分三步做,第一步生成匯編代碼,第二步生成目標文件,第三步生成可執行文件:

$ gcc -S main.c     (注意S是大寫的)
$ gcc -c main.s
$ gcc main.o

在main.c中這么寫到:
#include<stdio.h>
int m(){
printf("this is a test!");
return 0;
}
很明顯,這個程序不能運行,因為沒有main函數,試一下
gcc main.c -o main
報錯:
[ming@localhost codetest]$ gcc main.c -o main
/usr/lib/gcc/i686-redhat-linux/4.5.1/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: ld 返回 1

整個程序的入口點是 crt1.o中提供的 _start,它首先做一些初始化工作(以下稱為啟動例程,Startup Routine),然后調用C代碼中提供的 main函數。所以,以前我們說 main函數是程序的入口點其實不准確, _start才是真正的入口點,而 main函數是被 _start調用的。在_start中指名了要掉main,而程序中只有m函數,所以就運行不起來。
C程序的鏈接過程:
linux下gcc <wbr>In <wbr>function <wbr>`_start'
可以看到,,在生成main的可執行程序的時候,,其實還加入了其他的一些東西一起鏈接在一起執行的

main函數最標准的原型應該是int main(int argc, char *argv[]),也就是說啟動例程會傳兩個參數給main函數,這兩個參數的含義我們學了指針以后再解釋。我們到目前為止都把main函數的原型寫成int main(void),這也是C標准允許的,如果你認真分析了上一節的習題,你就應該知道,多傳了參數而不用是沒有問題的,少傳了參數卻用了則會出問題。

由於main函數是被啟動例程調用的,所以從main函數return時仍返回到啟動例程中,main函數的返回值被啟動例程得到,如果將啟動例程表示成等價的C代碼(實際上啟動例程一般是直接用匯編寫的),則它調用main函數的形式是:

exit(main(argc, argv));

也就是說,啟動例程得到main函數的返回值后,會立刻用它做參數調用exit函數。exit也是libc中的函數,它首先做一些清理工作,然后調用上一章講過的_exit系統調用終止進程,main函數的返回值最終被傳給_exit系統調用,成為進程的退出狀態。我們也可以在main函數中直接調用exit函數終止進程而不返回到啟動例程,例如:

#include <stdlib.h> int main(void) { exit(4); }

這樣和int main(void) { return 4; }的效果是一樣的。在Shell中運行這個程序並查看它的退出狀態:

$ ./a.out 
$ echo $?
4

按照慣例,退出狀態為0表示程序執行成功,退出狀態非0表示出錯。注意,退出狀態只有8位,而且被Shell解釋成無符號數,如果將上面的代碼改為exit(-1);return -1;,則運行結果為

$ ./a.out 
$ echo $?
255


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM