動態庫和靜態庫
前提:本文是基於Linux系統下的編程與學習
補充:頭文件衛士,避免頭文件重復包含。
//頭文件衛士 #ifndef __HEAD_H__ #define __HEAD_H__ //頭文件內容 #endif //__HEAD_H__
命令:nm
nm 二進制文件名; 可以查看二進制文件的符號表
那麽符號表裏都有哪些內容呢?
全局變量的名字, 靜態局部變量的名字, 函數的名字
靜態庫和動態庫
//main.c #include <stdio.h> #include "t_math.h" int main(){ printf("3+5=%d\n", add(3,5)); printf("5-3=%d\n", mul(5,3)); return 0; }
1 //t_math.c 2 5 int add(int a,int b){ 6 return a+b; 7 } 8 9 int mul(int a,int b){ 10 return a-b; 11 }
1 //t_math.h 2 #ifndef __T_MATH_H__ 3 #define __T_MATH_H__ 4 5 int add(int a,int b); 6 int mul(int a,int b); 7 8 #endif //__T_MATH_H__
生成靜態庫:
a. 將要加入靜態庫的源文件編譯成目標文件 gcc -c t_math.c
b. 將目標文件打包到靜態庫文件中 ar -r -o libtmath.a t_math.o
c. 使用靜態庫文件鏈接生成可執行文件
gcc -c main.c
gcc main.o -L. -ltmath
補充:-L路徑:鏈接器搜索庫文件的路徑; -l庫名:告訴鏈接器找那個庫
使用靜態庫生成的可執行文件,鏈接發生在生成可執行文件之前;稱為靜態鏈接。可執行文件不依賴於靜態庫文件。
生成動態庫(又稱共享庫):
a. 將要加入動態庫的源文件編譯成與位置無關的目標文件 gcc -c -fPIC t_math.c
b. 將第一步生成的目標文件打包到動態庫文件 gcc -shared -o libtmath.so t_math.o
c. 使用動態庫文件鏈接生成可執行文件
gcc -c main.c
gcc main.o -L. -ltmath
在生成可執行文件的時候,發生了鏈接,但是這個鏈接是一個虛的鏈接,真是的鏈接發生在代碼加載到內存的時候。這個真是的鏈接是動態鏈接。
使用動態鏈接庫生成的可執行文件,是動態鏈接。這個可執行文件依賴於動態庫文件。
如何查看一個可執行程序依賴於哪些動態庫文件呢? ldd
day03$ldd a.out
linux-gate.so.1 => (0xb76f5000)
libtmath.so => not found
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb751e000)
/lib/ld-linux.so.2 (0xb76f6000)
加載器 錯誤的原因就是加載器找不到動態庫。
解決這個問題,就需要告訴加載器到哪裏去找動態庫文件
兩種方法:
1、加載器的默認路徑
/usr/lib或者 /lib
鏈接器的默認路徑也是它。
2、使用環境變量告訴加載器到哪裏去找。
LD_LIBRARY_PATH 加載器使用的環境變量。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
動態鏈接和靜態鏈接的區別
執行文件的時候。 發生實際的鏈接。完全依賴動態庫
生成可執行文件的時候,發生實際的鏈接 不再依賴靜態庫
動態庫和靜態庫