C++ 編譯,執行過程 具體解釋。

來源:互聯網
上載者:User

標籤:http   $?   mail   tca   str   詞法   地址   this   進位   

        要更深入瞭解C++, 必需要知道一個程式從開始到結束都幹了些什麼, 怎麼乾的。

所以我從C++編譯到執行過程,解析下程式是怎麼跑的。

        首先,初略的說一下之前C++的編譯過程。C++編譯過程包含先行編譯-》彙編-》編譯-》連結。稱為一個可運行檔案。(Windows平台下為.exe檔案)。

先行編譯主要展開包括的標頭檔,宏定義等操作。比如一個簡單的main程式,編譯先行編譯後,的檔案對照。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center">

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center">  能夠看到裡面的宏已經被去掉了。

假設定了那個宏。那麼宏裡面的內容也會顯示出來。標頭檔也是。假設你包括了你一個.h 檔案,那麼整個.h檔案會包括進來。

     彙編過程,就是把已經先行編譯的檔案編譯成彙編代碼的過程。整個過程會包括文法,詞法的分析,和一些最佳化操作。

     編譯過程事實上是跟彙編能夠合成一個階段,變成目標代碼。也就是二進位檔案。

     連結過程是將單個編譯後的檔案連結成一個可運行程式。前面的先行編譯、彙編、編譯都是正對單個檔案,以一個檔案為一個編譯單元,而連結則是將全部關聯到的編譯後單元檔案和應用的到庫檔案。進行一次連結處理,之前編譯過的檔案 假設實用到其它檔案中面定義到的函數。全域變數。在這個過程中都會進行解析。

首先看看編譯後的檔案樣子(已VS2012編譯後的OBJ檔案為範例。不同編譯器 樣式可能會不同。

編譯前的檔案

#include "Car.h"
int main(int argc, char* argv[])
{
 Car* p = new Car();

 delete p;
 return 1;
}


編譯後的樣子(因為編譯後的檔案 資訊太多 僅僅貼出裡面未解析符號部分。

 UNDEF:00002DC4 ; int __thiscall Car::Car(Car *__hidden this)
UNDEF:00002DC4                 extrn ?

?

[email protected]@[email protected]:near ; CODE XREF: _main+63p
UNDEF:00002DC8 ; int __thiscall Car::~Car(Car *__hidden this)
UNDEF:00002DC8                 extrn ??

[email protected]@[email protected]:near
UNDEF:00002DC8                                         ; CODE XREF: Car::`scalar deleting destructor‘(uint)+26p
UNDEF:00002DCC ; __fastcall _RTC_CheckStackVars(x, x)
UNDEF:00002DCC                 extrn @[email protected]:near
UNDEF:00002DCC                                         ; CODE XREF: std::_String_alloc<0,std::_String_base_types<char,std::allocator<char>>>::_Alloc_proxy(void)+68p
UNDEF:00002DCC                                         ; $LN19+72p ...
UNDEF:00002DD0 ; __fastcall __security_check_cookie(x)
UNDEF:00002DD0                 extrn @[email protected]:near
UNDEF:00002DD0                                         ; CODE XREF: [email protected]@[email protected]@[email protected]@[email protected]+Fp
UNDEF:00002DD0                                         ; __ehhandler$??

[email protected][email protected]@@[email protected]@[email protected][email protected]@@@[email protected]@[email protected]@[email protected]@Z+Fp ...
UNDEF:00002DD4 ; __stdcall _CxxThrowException(x, x)

編譯後的檔案用(用反組譯碼成彙編代碼查看) 當中實現函數會變成一堆彙編指令。而那些引用到的在其它檔案中面實現的函數將會變成一個特點的符號(如上面中的調用Car類的建構函式 extrn[email protected]@[email protected]:near)這些符號稱做為解析的符號。表示在連結的時候須要被解析。

符號的產生名稱詳細跟編譯器有關,可是會保證一個類的某個函數名稱在同一個編譯裡面必須是唯一的,由於我們在先行編譯階段已經把Car.h包括進來所以編譯器能正確產生這個函數的名字。然後在連結的時候 會找到改名字的函數,把此標識名字替換為函數的地址。這樣就實現的連結。

在符號解析(symbol resolution)階段,連結器依照全部目標檔案和庫檔案出如今命令列中的順序從左至右依次掃描它們。在此期間它要維護若干個集合:(1)集合E是將被合并到一起組成可運行檔案的全部目標檔案集合。(2)集合U是未解析符號(unresolved symbols,比方已經被引用可是還未被定義的符號)的集合。(3)集合D是全部之前已被增加到E的目標檔案定義的符號集合。一開始,E、U、D都是空的。

(1): 對命令列中的每個輸入檔案f,連結器確定它是目標檔案還是庫檔案,假設它是目標檔案。就把f增加到E,並把f中未解析的符號和已定義的符號分別增加到U、D集合中。然後處理下一個輸入檔案。

(2): 假設f是一個庫檔案,連結器會嘗試把U中的全部未解析符號與f中各目標模組定義的符號進行匹配。假設某個目標模組m定義了一個U中的未解析符號,那麼就把 m增加到E中,並把m中未解析的符號和已定義的符號分別增加到U、D集合中。不斷地對f中的全部目標模組反覆這個過程直至到達一個不動點(fixed point),此時U和D不再變化。而那些未增加到E中的f裡的目標模組就被簡單地丟棄,連結器繼續處理下一輸入檔案。

(3): 假設處理過程中往D增加一個已存在的符號,或者當掃描全然部輸入檔案時U非空。連結器報錯並停止動作。否則,它把E中的全部目標檔案合并在一起產生可運行檔案。





C++ 編譯,執行過程 具體解釋。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.