源文件是如何通過編譯器換成可執行文件的?
可執行文件被加載到內存后是如何運行的?
程序運行是內存上的棧和堆是如何進行的?
計算機只能運行本地代碼(機器語言代碼)
編譯器負責轉換源代碼
讀入的源代碼還要經過語法解析、句法解析、語義解析等,才能生成本地代碼
編譯器不僅和編程語言的種類有關,和CPU的類型也是相關的。
僅靠編譯是無法得到可執行文件的
本地文件是無法直接運行的,為了得到可以運行的EXE文件,編譯之后還需要進行“鏈接”處理。
把多個目標文件結合,生成1個EXE文件的處理就是鏈接,運行連接的程序就稱這鏈接器。
啟動及庫文件
c0w32.obj 這個目標文件記述的是同所有程序起始位置相結合的處理內容,程序的啟動。
庫文件指的是把多個目標文件集成保存到一個文件中的形式。鏈接器指定庫文件后,就會從中把需要的目標文件抽取出來,并同其他目標文件結合生成EXE文件。
不是通過源代碼形式而是通過庫文件形式和編譯器一起提供的的函數稱為標準函數。
DLL文件及導入庫
windows 以函數的形式為應用提供了各種功能。這些形式的函數稱為API,并不是C語言的標準函數。
API的目標文件,并不是存儲在通常的庫文件中,而存儲在名為DLL文件的特殊庫文件中,這樣的庫文件稱之為導入庫。DLL文件是程序運行時動態結合的文件。(個人覺得可以理解為系統文件)
可執行文件運行時的必要條件
每次運行是,程序內的變量及函數被分配到的內存地址是不同的。那么在EXE文件中,變量和函數的內存地址的值,是如何來表示的呢?
答案就是EXE文件中給變量及函數分配了虛擬的內存地址。在程序運行時,虛擬的內存地址會轉換成實際的內存地址。鏈接器會在EXE文件的開頭,追加轉換內存地址所需的必要信息。這個信息稱為再配置信息。這個再配置信息,變成為了變量和函數的相對地址。
程序加載時會生成棧和堆
當程序加載到內存后,除此之外還會額外生成兩個組,那就棧和堆。棧是用來存儲函數內部臨時使用的變量(局部變量),以及函數調用時所用的參數的內存區域。堆是用來存儲程序運行時的任意數據及對象的內存領域。
因此,內存中的程序,就是由用于變量的內存空間,用于函數的內存空間,用于棧的內存空間,用于堆的內存空間。當然加載操作系統的內存空間是另外一回事了。
棧中對數據進行存儲和舍棄的代碼,是由編譯器自動生成的,不需要程序員參與。每當函數調用時會得到申請分配,函數處理完成后自動釋放。堆則要根據程序員編寫的程序,來明確進行申請分配或釋放。
直接今天才對內存管理有了個基本清晰的了解,總算找到了一本說得清楚的書了。不過還是有點沒太理解堆中的任意數據指的是?還有類和對象在內存的處理方式。