At this point you have an executable.
號在這一點上,你有目標文件,這是不是在他們自己的,可執行的。
But if you actually run that executable what happens?
事情是這樣的:
h2co3-macbook:~ h2co3$ clang -Wall -o quirk.o quirk.c -c
h2co3-macbook:~ h2co3$ chmod +x quirk.o
h2co3-macbook:~ h2co3$ ./quirk.o
-bash: ./quirk.o: Malformed Mach-o file
我告訴你這是不是一個可執行文件。
Is the problem that you may have included *.h files, and those only contain function prototypes?
其實很接近。翻譯單元(.c文件)(通常)被轉換爲代表其功能的彙編/機器代碼。如果它調用一個函數,那麼文件中將會有該函數的引用,但沒有定義。
So if you actually call one of the functions from those files, it won't have a definition and your program will crash?
正如我所說,它甚至不會運行。讓我重複一遍:目標文件是不可執行。
what exactly does linking do, under the hood? How does it find the .c file associated with the .h that you included [...]
事實並非如此。它會查找由.c文件生成的其他對象文件,並最終查找庫(其實質上只是其他對象文件的集合)。
它找到它們是因爲你告訴它要尋找什麼。假設你有它由該相互調用的函數的兩個.c文件的一個項目,這是不行的:
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc -o my_prog file1.o
它會失敗,並鏈接錯誤:鏈接器將無法找到的定義在file2.c
(和file2.o
)中實施的功能。但是,這將工作:
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc -o my_prog file1.o file2.o
[...] and how does it inject that into your machine code?
對象文件包含存根引用(通常在函數入口點地址或明確的,人類可讀的名字的形式)來調用它們的功能。然後,鏈接器查看每個庫和目標文件,找到引用(如果找不到函數定義,則拋出錯誤),然後用實際的「調用此函數」機器代碼指令替換存根引用。 (是的,這在很大程度上簡化了,但沒有你問一個具體的架構和具體的編譯器/連接器,這是很難說更準確...)
Is static when you actually recompile the source of the library for every executable you create?
號靜態鏈接意味着機器代碼庫的對象文件實際上被複制/合併到最終的可執行文件中。動態鏈接意味着庫被加載到內存中一次,然後當啓動可執行文件時,操作系統解析上述存根函數引用。庫中的機器代碼不會被複制到最終的可執行文件中。 (所以這裏,工具鏈中的鏈接程序只做部分工作。)
以下內容可以幫助您實現啓示:如果靜態鏈接可執行文件,它將是自包含的。它可以在任何地方運行(無論如何都是在兼容的架構上)。如果您動態鏈接它,則只有在該計算機上安裝了該程序引用的所有庫時纔會在機器上運行。
So you compile one executable library that is shared by all of your processes that use it? How is that possible, exactly? Wouldn't it be outside of the address space of the processes trying to access it?
OS的動態鏈接器/裝載器組件負責所有的這一點。
Also, for dynamic linking, don't you still need to compile the library at some juncture in time?
正如我已經提到:是的,它已經編譯。然後它會在某個點(通常是第一次使用時)加載到內存中。
When is it compiled?
有一段時間才能使用。通常情況下,編譯一個庫,然後將其安裝到系統上的某個位置,以便操作系統和編譯器/鏈接器知道它的存在,然後開始編譯(使用該庫的程序,即鏈接)。不早。
可能的重複[在實際中如何C++鏈接工作?](http://stackoverflow.com/questions/12122446/how-does-c-linking-work-in-practice) –