1. 程式人生 > >動態庫和靜態庫

動態庫和靜態庫

linu not fine 執行文件 port pic 靜態庫 可執行 生成可執行文件

前提:本文是基於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:./

動態鏈接和靜態鏈接的區別
執行文件的時候。 發生實際的鏈接。完全依賴動態庫
生成可執行文件的時候,發生實際的鏈接 不再依賴靜態庫

動態庫和靜態庫