能夠參考《程序員的自我修養》裝載、連接和庫linux
一、程序並非從main函數開始的。好比下面的程序:程序員
#include <stdio.h> #include <stdlib.h> int a = 3; int main(int argc, char *argv[]) { int *p = (int *)malloc(sizeof(int)); scanf("%d", p); printf("%d", a + *p); free(p); } #include <string> using namespace std; string v; double foo() { return 1.0; } double g = foo(); int main() {}
從代碼中咱們能夠看到,在程序剛剛執行到main的時候,全局變量的初始化過程已經結束了(a的值已經肯定),main函數的兩個參數(argc和argv)也被正確傳了進來。此外,在你不知道的時候,堆和棧的初始化悄悄地完成了,一些系統I/O也被初始化了,所以能夠放心地使用printf和malloc。函數
第二個C++程序,對象v的構造函數,以及用於初始化全局變量g的函數foo都會在main以前調用。spa
操做系統裝載程序以後,首先運行的代碼並非main的第一行,而是某些別的代碼,這些代碼負責準備好main函數執行所須要的環境,而且負責調用main函數,這時候你才能夠在main函數裏放心大膽地寫各類代碼:申請內存、使用系統調用、觸發異常、訪問I/O。在main返回以後,它會記錄main函數的返回值,調用atexit註冊的函數,而後結束進程。操作系統
運行這些代碼的函數成爲入口函數或入口點,視平臺的不一樣而有不一樣的名字。程序的入口點其實是一個程序的初始化和結束部分,它每每是運行庫的一部分。一個典型的程序運行步驟大體以下:線程
(1)操做系統在建立進程後,把控制權交到了程序的入口,這個入口每每是運行庫中的某個入口函數。對象
(2)入口函數對運行庫和程序運行環境進行初始化,包括堆、I/O、線程、全局變量構造,等等blog
(3)入口函數在完成初始化以後,調用main函數,正式開始執行程序主題部分。進程
(4)main函數執行完畢之後,返回到入口函數,入口函數進行清理工做,包括全局變量析構、堆銷燬、關閉I/O等,而後進行系統調用結束進程。內存