編譯與靜態鏈接

  • 將每個源代碼獨立編譯之後,需要將他們“組裝”起來,該過程便是鏈接。鏈接主要的工作就是將各個模塊之間相互引用的地方處理好,使各個模塊之間能夠正確的銜接。

  • 鏈接的過程主要包括了地址和空間分配、地址綁定和重定位等操作。

  • 最基本的鏈接過程如下,每個模塊的源代碼文件(.c)->(.o)->(.out);

    wKiom1SRTgqCyerBAAFMXEAi_4o022.jpg

  • 如果程序模塊main.c中調用了func.c中的函數foo(),因此每一次main.c中調用foo()時,必須要知道函數的地址,但是由於每個模塊在編譯時是獨立編譯,並不知道foo()函數的確切地址,那該怎麼辦呢?編譯器會先把這些調用foo()的指令的目標地址擱置,等待鏈接的時候鏈接器去修改其目標地址;如果沒有連接器的話,那我們需要手動將把調用foo的指令進行修改,如果fun.c模塊重新編譯的話,那麼foo的地址有可能發生變化,那麼需要重新調整其他模塊中調用foo指令的目標地址,這將是程序員的噩夢,因此這些工作都交給了連接器來做,因爲鏈接器在鏈接的時候會根據你引用的符號foo,自動的去func.c模塊中查找foo的地址,然後將其他模塊引用foo的指令重新修改,讓它的目標地址爲真正foo函數的地址。

  • 在編譯時,引用其他模塊中的函數或者全局變量,本模塊的響應指令的目標地址默認爲0,先擱置不管,等連接的時候連接器會去修改它,該過程也別叫做重定位。

  • 發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章