CC++編譯器和調(diào)試器以及靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)使用匯總_第1頁(yè)
CC++編譯器和調(diào)試器以及靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)使用匯總_第2頁(yè)
CC++編譯器和調(diào)試器以及靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)使用匯總_第3頁(yè)
CC++編譯器和調(diào)試器以及靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)使用匯總_第4頁(yè)
CC++編譯器和調(diào)試器以及靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)使用匯總_第5頁(yè)
已閱讀5頁(yè),還剩10頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C/C+ 編譯器和調(diào)試器以及靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)使用匯總閱讀提示:本文是C/C+ 編譯器和調(diào)試器以及靜態(tài)庫(kù)、動(dòng)態(tài)庫(kù)使用匯總 大多數(shù)unix系統(tǒng)下面的調(diào)試器的使用方法如下: gdb介紹GNU 的調(diào)試器稱為 gdb,該程序是一個(gè)交互式工具,工作在字符模式。在 X Window 系統(tǒng)中,有一個(gè) gdb 的 前端圖形工具,稱為 xxgdb。gdb 是功能強(qiáng)大的調(diào)試程序,可完成如下的調(diào)試任務(wù): * 設(shè)置斷點(diǎn); * 監(jiān)視程序變量的值; * 程序的單步執(zhí)行; * 修改變量的值。 在可以使用 gdb 調(diào)試程序之前,必須使用 -g 選項(xiàng)編譯源文件??稍?makefile 中如下定義 CFLAGS 變量: CFLAGS

2、 = -g 運(yùn)行 gdb 調(diào)試程序時(shí)通常使用如下的命令: gdb progname 在 gdb 提示符處鍵入help,將列出命令的分類,主要的分類有: * aliases:命令別名 * breakpoints:斷點(diǎn)定義; * data:數(shù)據(jù)查看; * files:指定并查看文件; * internals:維護(hù)命令; * running:程序執(zhí)行; * stack:調(diào)用棧查看; * statu:狀態(tài)查看; * tracepoints:跟蹤程序執(zhí)行。 鍵入 help 后跟命令的分類名,可獲得該類命令的詳細(xì)清單。 gdb 的常用命令命令 解釋 break NUM 在指定的行上設(shè)置斷點(diǎn)。 bt 顯示所

3、有的調(diào)用棧幀。該命令可用來(lái)顯示函數(shù)的調(diào)用順序。 clear 刪除設(shè)置在特定源文件、特定行上的斷點(diǎn)。其用法為:clear FILENAME:NUM。 continue 繼續(xù)執(zhí)行正在調(diào)試的程序。該命令用在程序由于處理信號(hào)或斷點(diǎn)而 導(dǎo)致停止運(yùn)行時(shí)。 display EXPR 每次程序停止后顯示表達(dá)式的值。表達(dá)式由程序定義的變量組成。 file FILE 裝載指定的可執(zhí)行文件進(jìn)行調(diào)試。 help NAME 顯示指定命令的幫助信息。 info break 顯示當(dāng)前斷點(diǎn)清單,包括到達(dá)斷點(diǎn)處的次數(shù)等。 info files 顯示被調(diào)試文件的詳細(xì)信息。 info func 顯示所有的函數(shù)名稱。 info lo

4、cal 顯示當(dāng)函數(shù)中的局部變量信息。 info prog 顯示被調(diào)試程序的執(zhí)行狀態(tài)。 info var 顯示所有的全局和靜態(tài)變量名稱。 kill 終止正被調(diào)試的程序。 list 顯示源代碼段。 make 在不退出 gdb 的情況下運(yùn)行 make 工具。 next 在不單步執(zhí)行進(jìn)入其他函數(shù)的情況下,向前執(zhí)行一行源代碼。 print EXPR 顯示表達(dá)式 EXPR 的值。 gdb 使用范例- 清單 一個(gè)有錯(cuò)誤的 C 源程序 bugging.c - #include #include static char buff 256; static char* string; int main () pri

5、ntf ("Please input a string: "); gets (string); printf ("nYour string is: %sn", string); - 上面這個(gè)程序非常簡(jiǎn)單,其目的是接受用戶的輸入,然后將用戶的輸入打印出來(lái)。該程序使用了一個(gè)未經(jīng)過(guò)初 始化的字符串地址 string,因此,編譯并運(yùn)行之后,將出現(xiàn) Segment Fault 錯(cuò)誤: $ gcc -o test -g test.c $ ./test Please input a string: asfd Segmentation fault (core dumpe

6、d) 為了查找該程序中出現(xiàn)的問(wèn)題,我們利用 gdb,并按如下的步驟進(jìn)行: 1運(yùn)行 gdb bugging 命令,裝入 bugging 可執(zhí)行文件; 2執(zhí)行裝入的 bugging 命令; 3使用 where 命令查看程序出錯(cuò)的地方; 4利用 list 命令查看調(diào)用 gets 函數(shù)附近的代碼; 5唯一能夠?qū)е?gets 函數(shù)出錯(cuò)的因素就是變量 string。用 print 命令查看 string 的值; 6在 gdb 中,我們可以直接修改變量的值,只要將 string 取一個(gè)合法的指針值就可以了,為此,我們?cè)诘?11 行處設(shè)置斷點(diǎn); 7程序重新運(yùn)行到第 11 行處停止,這時(shí),我們可以用 set v

7、ariable 命令修改 string 的取值; 8然后繼續(xù)運(yùn)行,將看到正確的程序運(yùn)行結(jié)果。 運(yùn)行 gcc/egcs GCC 是 GNU 的 C 和 C+ 編譯器。實(shí)際上,GCC 能夠編譯三種語(yǔ)言:C、C+ 和 Object C(C 語(yǔ)言的一種面向?qū)ο髷U(kuò)展)。利用 gcc 命令可同時(shí)編譯并連接 C 和 C+ 源程序。 如果你有兩個(gè)或少數(shù)幾個(gè) C 源文件,也可以方便地利用 GCC 編譯、連接并生成可執(zhí)行文件。例如,假設(shè)你有 兩個(gè)源文件 main.c 和 factorial.c 兩個(gè)源文件,現(xiàn)在要編譯生成一個(gè)計(jì)算階乘的程序。 清單 factorial.c - #include #include i

8、nt factorial (int n) if (n <= 1) return 1; else return factorial (n - 1) * n; - - 清單 main.c - #include #include int factorial (int n); int main (int argc, char *argv) int n; if (argc < 2) printf ("Usage: %s nn", argv 0); return -1; else n = atoi (argv1); printf ("Factorial of %d

9、 is %d.n", n, factorial (n); return 0; - 利用如下的命令可編譯生成可執(zhí)行文件,并執(zhí)行程序: $ gcc -o factorial main.c factorial.c $ ./factorial 5 Factorial of 5 is 120. GCC 可同時(shí)用來(lái)編譯 C 程序和 C+ 程序。一般來(lái)說(shuō),C 編譯器通過(guò)源文件的后綴名來(lái)判斷是 C 程序還是 C+ + 程序。在 Linux 中,C 源文件的后綴名為 .c,而 C+ 源文件的后綴名為 .C 或 .cpp。 但是,gcc 命令只能編譯 C+ 源文件,而不能自動(dòng)和 C+ 程序使用的庫(kù)連接。

10、因此,通常使用 g+ 命令來(lái)完 完成 C+ 程序的編譯和連接,該程序會(huì)自動(dòng)調(diào)用 gcc 實(shí)現(xiàn)編譯。 假設(shè)我們有一個(gè)如下的 C+ 源文件(hello.C): #include void main (void) cout << "Hello, world!" << endl; 則可以如下調(diào)用 g+ 命令編譯、連接并生成可執(zhí)行文件: $ g+ -o hello hello.C $ ./hello Hello, world! gcc/egcs 的主要選項(xiàng)選項(xiàng) 解釋 -ansi 只支持 ANSI 標(biāo)準(zhǔn)的 C 語(yǔ)法。這一選項(xiàng)將禁止 GNU C 的某些特色, 例如

11、 asm 或 typeof 關(guān)鍵詞。 -c 只編譯并生成目標(biāo)文件。 -DMACRO 以字符串“1”定義 MACRO 宏。 -DMACRO=DEFN 以字符串“DEFN”定義 MACRO 宏。 -E 只運(yùn)行 C 預(yù)編譯器。 -g 生成調(diào)試信息。GNU 調(diào)試器可利用該信息。 -IDIRECTORY 指定額外的頭文件搜索路徑DIRECTORY。 -LDIRECTORY 指定額外的函數(shù)庫(kù)搜索路徑DIRECTORY。 -lLIBRARY 連接時(shí)搜索指定的函數(shù)庫(kù)LIBRARY。 -m486 針對(duì) 486 進(jìn)行代碼優(yōu)化。 -o FILE 生成指定的輸出文件。用在生成可執(zhí)行文件時(shí)。 -O0 不進(jìn)行優(yōu)化處理。

12、-O 或 -O1 優(yōu)化生成代碼。 -O2 進(jìn)一步優(yōu)化。 -O3 比 -O2 更進(jìn)一步優(yōu)化,包括 inline 函數(shù)。 -shared 生成共享目標(biāo)文件。通常用在建立共享庫(kù)時(shí)。 -static 禁止使用共享連接。 -UMACRO 取消對(duì) MACRO 宏的定義。 -w 不生成任何警告信息。 -Wall 生成所有警告信息。 SCO UNIX下面dbaxtra的調(diào)試技術(shù) 在sco unix下編程大多離不開(kāi)C語(yǔ)言,即使是數(shù)據(jù)庫(kù)應(yīng)用也有很多是與c搭配使用的,例如informix esql/c 就可以在c語(yǔ)言中嵌入sql 語(yǔ)句。很多人認(rèn)為在unix下寫(xiě)程序是件很痛苦的事情,其中一個(gè)很重要原因是不知

13、道在unix下怎樣調(diào)試程序。其實(shí)在sco unix源碼調(diào)試器是dbxtra或dbXtra,linux下是gdb。它們類似turbo c的調(diào)試器,可以跟蹤源碼變量。在unix 下調(diào)試程序有如下傳統(tǒng)方法 一、在要調(diào)試語(yǔ)句之前,輸出要調(diào)試的變量,利用printf()函數(shù)。 二、寫(xiě)日志文件,把結(jié)果輸出到文件中避免屏幕混亂,利用fprintf()函數(shù)。 三、利用sco 內(nèi)置調(diào)試器dbxtra或dbXtra。 dbxtra 適用字符界面,在sco unix的圖形界面用dbXtra。(編按:請(qǐng)注意大小寫(xiě)) 以下是dbxtra基本命令: c cont 在斷點(diǎn)后繼續(xù)執(zhí)行 d delete 刪除所設(shè)斷點(diǎn) h he

14、lp 幫助 e edit 編輯源程序 n next 源程序區(qū)的內(nèi)容向下翻一屏。 p print 顯示變量 q quit 退出dbxtra r run 運(yùn)行程序,直到遇上設(shè)置的斷點(diǎn) rr rerun 再次運(yùn)行 s step 單步運(yùn)行 st stop 設(shè)置斷點(diǎn) j status 顯示當(dāng)前斷點(diǎn) t where 顯示當(dāng)前狀態(tài),列出所有設(shè)置的變量值 di display 開(kāi)顯示窗,用于查看變量 ud undisplay 刪除顯示窗的條目 f forward 源程序區(qū)的內(nèi)容向上 翻一屏。 B backward 源程序區(qū)的內(nèi)容向下 翻一屏。 Stopi stop inst 設(shè)置斷點(diǎn) tracei trace

15、 inst跟蹤子程序 dbxtra options objectfile dbxtra 在啟動(dòng)時(shí)有個(gè)參數(shù)-Idir值得一提.我們?cè)诰帉?xiě)一個(gè)較大程序的時(shí)候,通常源程序和編譯生成的可執(zhí)行文件都放在不同的目錄中,這樣便于管理。默認(rèn)dbxtra將在可執(zhí)行文件所在的目錄下找匹配c的源程序。當(dāng)我們啟動(dòng)時(shí),指定-I參數(shù),dbxtra就會(huì)到我們指定的目錄下找匹配的c程序。 例如: dbxtra -I"workc" program1 源程序在用cc編譯時(shí)要帶上-g 參數(shù),這樣是加上符號(hào)表等調(diào)試信息。只有這樣編譯過(guò)的文件,dbxtra才可以調(diào)試。調(diào)試信息使源代碼和機(jī)器碼關(guān)聯(lián)。 下面這個(gè)C程序輸

16、出結(jié)果和我們的預(yù)想結(jié)果不一樣,說(shuō)明某些地方有錯(cuò)誤。我們用調(diào)試器來(lái)調(diào)試它: 程序一: t.c main() int i=10 ,*p1; float j=1.5,*p2; p1=& p2=& p2=p1; printf("%d,%dn",*p1,*p2); 首先帶上-g參數(shù)編譯 cc -g -o t t.c 啟動(dòng)調(diào)試器 dbxtra t 屏幕顯示: 1.main() 2. int i=10 ,*p1; 3. float j=1.5,*p2; 4. p1=& 5. p2=& 6. p2=p1; 7. printf("%d,%dn&quo

17、t;,*p1,*p2); 8. Cbrowse File:t.c Func.- Readubg symbolic information Type 'help' for help (dbxtra) (dbxtra) 設(shè)置斷點(diǎn): (dbxtra)stop at 5 運(yùn)行: (dbxtra) run 程序自動(dòng)在第5行停下。 這時(shí)我們可以看變量的值。 (dbxtra) print *p1 單步執(zhí)行。 (dbxtra) step 程序?qū)?zhí)行第5行源碼,指針將移到第6行。 (dbxtra) print *p2 (dbxtra) step 程序執(zhí)行了第6行源碼后,將指針移到第7行。 (db

18、xtra) print *p1 , *p2 我們發(fā)現(xiàn) 在執(zhí)行了第6行源碼后,*p1,*p2的值就不對(duì)了,所以問(wèn)題就出在第6行上。仔細(xì)檢查后發(fā)現(xiàn)指針p1指向整型,指針p2指向?qū)嵭?。它們之間的賦值要進(jìn)行強(qiáng)制類型轉(zhuǎn)換。這種錯(cuò)誤在C程序中是很常見(jiàn)的。 有時(shí)我們?cè)谡{(diào)試一些程序時(shí),要在整個(gè)程序運(yùn)行中時(shí)刻監(jiān)視莫些變量的值,例如程序一中我們要時(shí)刻了解*p1,*p2的值,除了在每一行程序執(zhí)行完后,打print *p1,*p2外,還可以開(kāi)一個(gè)顯示窗口。 (dbxtra)display *p1,*p2 用undisplay 刪掉不想要的變量。 有些程序運(yùn)行時(shí)要帶參數(shù),mycat /etc/passwd 在調(diào)試時(shí)候

19、(dbxtra) run '/etc/passwd' 再運(yùn)行時(shí),無(wú)需再寫(xiě)一遍參數(shù)。 (dbxtra) rerun 在涉及到curses庫(kù)編程或屏幕有大量的人機(jī)界面時(shí),為了調(diào)試方便,我們可以把程序輸出結(jié)果重定向到個(gè)虛屏。 (dbxtra) run >/dev/tty03 當(dāng)然要先把tty03 disable 掉。(disable tty03) 創(chuàng)建和使用靜態(tài)庫(kù)詳細(xì)的使用情況,請(qǐng)大家man手冊(cè),這里只介紹一下。靜態(tài)庫(kù)相對(duì)的比較簡(jiǎn)單。 創(chuàng)建一個(gè)靜態(tài)庫(kù)是相當(dāng)簡(jiǎn)單的。通常使用 ar 程序把一些目標(biāo)文件(.o)組合在一起,成為一個(gè)單獨(dú)的庫(kù),然后運(yùn)行 ranlib,以給庫(kù)加入一些索引信

20、息。 創(chuàng)建和使用共享庫(kù)特殊的編譯和連接選項(xiàng) -D_REENTRANT 使得預(yù)處理器符號(hào) _REENTRANT 被定義,這個(gè)符號(hào)激活一些宏特性。 -fPIC 選項(xiàng)產(chǎn)生位置獨(dú)立的代碼。由于庫(kù)是在運(yùn)行的時(shí)候被調(diào)入,因此這個(gè)選項(xiàng)是必需的,因?yàn)樵诰幾g的時(shí)候,裝入內(nèi)存的地址還不知道。如果不使用這個(gè)選項(xiàng),庫(kù)文件可能不會(huì)正確運(yùn)行。 -shared 選項(xiàng)告訴編譯器產(chǎn)生共享庫(kù)代碼。 -Wl,-soname -Wl 告訴編譯器將后面的參數(shù)傳遞到連接器。而 -soname 指定了共享庫(kù)的 soname。 可以把庫(kù)文件拷貝到 /etc/ld.so.conf 中列舉出的任何目錄中,并以 root 身份運(yùn)行 ldconfi

21、g;或者 運(yùn)行 export LD_LIBRARY_PATH='pwd',它把當(dāng)前路徑加到庫(kù)搜索路徑中去。 使用高級(jí)共享庫(kù)特性1. ldd 工具 ldd 用來(lái)顯示執(zhí)行文件需要哪些共享庫(kù), 共享庫(kù)裝載管理器在哪里找到了需要的共享庫(kù). 2. soname 共享庫(kù)的一個(gè)非常重要的,也是非常難的概念是 soname簡(jiǎn)寫(xiě)共享目標(biāo)名(short for shared object name)。這是一個(gè)為共享庫(kù)(.so)文件而內(nèi)嵌在控制數(shù)據(jù)中的名字。如前面提到的,每一個(gè)程序都有一個(gè)需要使用的庫(kù)的清單。這個(gè)清單的內(nèi)容是一系列庫(kù)的 soname,如同 ldd 顯示的那樣,共享庫(kù)裝載器必須找到這個(gè)

22、清單。 soname 的關(guān)鍵功能是它提供了兼容性的標(biāo)準(zhǔn)。當(dāng)要升級(jí)系統(tǒng)中的一個(gè)庫(kù)時(shí),并且新庫(kù)的 soname 和老的庫(kù)的 soname 一樣,用舊庫(kù)連接生成的程序,使用新的庫(kù)依然能正常運(yùn)行。這個(gè)特性使得在 Linux 下,升級(jí)使用共享庫(kù)的程序和定位錯(cuò)誤變得十分容易。 在 Linux 中,應(yīng)用程序通過(guò)使用 soname,來(lái)指定所希望庫(kù)的版本。庫(kù)作者也可以通過(guò)保留或者改變 soname 來(lái)聲明,哪些版本是相互兼容的,這使得程序員擺脫了共享庫(kù)版本沖突問(wèn)題的困擾。 查看/usr/local/lib 目錄,分析 MiniGUI 的共享庫(kù)文件之間的關(guān)系 3. 共享庫(kù)裝載器 當(dāng)程序被調(diào)用的時(shí)候,Linux 共

23、享庫(kù)裝載器(也被稱為動(dòng)態(tài)連接器)也自動(dòng)被調(diào)用。它的作用是保證程序所需要的所有適當(dāng)版本的庫(kù)都被調(diào)入內(nèi)存。共享庫(kù)裝載器名字是 ld.so 或者是 ld-linux.so,這取決于 Linux libc 的版本,它必須使用一點(diǎn)外部交互,才能完成自己的工作。然而它接受在環(huán)境變量和配置文件中的配置信息。 文件 /etc/ld.so.conf 定義了標(biāo)準(zhǔn)系統(tǒng)庫(kù)的路徑。共享庫(kù)裝載器把它作為搜索路徑。為了改變這個(gè)設(shè)置,必須以 root 身份運(yùn)行 ldconfig 工具。這將更新 /etc/ls.so.cache 文件,這個(gè)文件其實(shí)是裝載器內(nèi)部使用的文件之一。 可以使用許多環(huán)境變量控制共享庫(kù)裝載器的操作(表1-

24、4+)。 表 1-4+ 共享庫(kù)裝載器環(huán)境變量 變量 含義 LD_AOUT_LIBRARY_PATH 除了不使用 a.out 二進(jìn)制格式外,與 LD_LIBRARY_PATH 相同。 LD_AOUT_PRELOAD 除了不使用 a.out 二進(jìn)制格式外,與 LD_PRELOAD 相同。 LD_KEEPDIR 只適用于 a.out 庫(kù);忽略由它們指定的目錄。 LD_LIBRARY_PATH 將其他目錄加入庫(kù)搜索路徑。它的內(nèi)容應(yīng)該是由冒號(hào) 分隔的目錄列表,與可執(zhí)行文件的 PATH 變量具有相同的格式。 如果調(diào)用設(shè)置用戶 ID 或者進(jìn)程 ID 的程序,該變量被忽略。 LD_NOWARN 只適用于 a.

25、out 庫(kù);當(dāng)改變版本號(hào)是,發(fā)出警告信息。 LD_PRELOAD 首先裝入用戶定義的庫(kù),使得它們有機(jī)會(huì)覆蓋或者重新定義標(biāo)準(zhǔn)庫(kù)。 使用空格分開(kāi)多個(gè)入口。對(duì)于設(shè)置用戶 ID 或者進(jìn)程 ID 的程序, 只有被標(biāo)記過(guò)的庫(kù)才被首先裝入。在 /etc/ld.so.perload 中指定 了全局版本號(hào),該文件不遵守這個(gè)限制。 4. 使用 dlopen 另外一個(gè)強(qiáng)大的庫(kù)函數(shù)是 dlopen()。該函數(shù)將打開(kāi)一個(gè)新庫(kù),并把它裝入內(nèi)存。該函數(shù)主要用來(lái)加載庫(kù)中的符號(hào),這些符號(hào)在編譯的時(shí)候是不知道的。比如 Apache Web 服務(wù)器利用這個(gè)函數(shù)在運(yùn)行過(guò)程中加載模塊,這為它提供了額外的能力。一個(gè)配置文件控制了加載模塊

26、的過(guò)程。這種機(jī)制使得在系統(tǒng)中添加或者刪除一個(gè)模塊時(shí),都不需要重新編譯了。 可以在自己的程序中使用 dlopen()。dlopen() 在 dlfcn.h 中定義,并在 dl 庫(kù)中實(shí)現(xiàn)。它需要兩個(gè)參數(shù):一個(gè)文件名和一個(gè)標(biāo)志。文件名可以是我們學(xué)習(xí)過(guò)的庫(kù)中的 soname。標(biāo)志指明是否立刻計(jì)算庫(kù)的依賴性。如果設(shè)置為 RTLD_NOW 的話,則立刻計(jì)算;如果設(shè)置的是 RTLD_LAZY,則在需要的時(shí)候才計(jì)算。另外,可以指定 RTLD_GLOBAL,它使得那些在以后才加載的庫(kù)可以獲得其中的符號(hào)。 當(dāng)庫(kù)被裝入后,可以把 dlopen() 返回的句柄作為給 dlsym() 的第一個(gè)參數(shù),以獲得符號(hào)在庫(kù)中的地

27、址。使用這個(gè)地址,就可以獲得庫(kù)中特定函數(shù)的指針,并且調(diào)用裝載庫(kù)中的相應(yīng)函數(shù)。LINUX動(dòng)態(tài)鏈接庫(kù)的使用 一、編寫(xiě)合格的動(dòng)態(tài)鏈接庫(kù)頭文件 C語(yǔ)言的頭文件,可供一個(gè)或多個(gè)程序引用,里面一般定義程序所需的常量,自定義類型及函數(shù)原型說(shuō)明等.其中的函數(shù)原型說(shuō)明,則供編譯器檢查語(yǔ)法,用于排除引用參數(shù)時(shí)類型不一致的錯(cuò)誤.只有編寫(xiě)合格的動(dòng)態(tài)鏈接庫(kù)頭文件,程序員才能正確使用動(dòng)態(tài)鏈接庫(kù)內(nèi)的函數(shù). 動(dòng)態(tài)鏈接庫(kù)頭文件要采用C語(yǔ)言標(biāo)準(zhǔn)格式,其中的動(dòng)態(tài)函數(shù)原型定義,不必象上文介紹的那樣用(*動(dòng)態(tài)函數(shù)名)的描述形式.請(qǐng)看下面的例子每行開(kāi)始的數(shù)字為所在行行號(hào),為筆者添加,供注解使用) 1 /* adatetime.h : 縱

28、橫軟件制作中心雨亦奇(zhsoft)編寫(xiě), 2002-03-06. */ 2 3 #ifndef _DATETIME_H 4 5 #define _DATETIME_H 6 7 /* 日期結(jié)構(gòu) */ 8 typedef struct 9 10 int year; 11 int mon; 12 int day; 13 DATETYPE; 14 15 /* 時(shí)間結(jié)構(gòu) */ 16 typedef struct 17 18 char hour; 19 char min; 20 char sec; 21 TIMETYPE; 22 23 int getdate(DATETYPE *d); /* 取當(dāng)前日期

29、 */ 24 int gettime(TIMETYPE *t); /* 取當(dāng)前時(shí)間 */ 25 26 #endif 27 注:與上文的datetime.h文件比較,從該頭文件第23,24行可以看到,動(dòng)態(tài)函數(shù)getdate,gettime的原型定義改變了,不再使用(*getdate),(*gettime)的格式了(這種格式使用較為羅嗦). 二、正確編譯與命名動(dòng)態(tài)鏈接庫(kù) 為了讓GCC編譯器生成動(dòng)態(tài)鏈接庫(kù),編譯時(shí)須加選項(xiàng)-shared.(這點(diǎn)須牢記) LINUX系統(tǒng)中,為了讓動(dòng)態(tài)鏈接庫(kù)能被系統(tǒng)中其它程序共享,其名字應(yīng)符合“l(fā)ib*.so*”這種格式.如果某個(gè)動(dòng)態(tài)鏈接庫(kù)不符合此格式,則LINUX的動(dòng)態(tài)

30、鏈接庫(kù)自動(dòng)裝入程序(ld.so)將搜索不到此鏈接庫(kù),其它程序也無(wú)法共享之. 格式中,第一個(gè)*通常表示為簡(jiǎn)寫(xiě)的庫(kù)名,第二個(gè)*通常表示為該庫(kù)的版本號(hào).如:在我的系統(tǒng)中,基本C動(dòng)態(tài)鏈接庫(kù)的名字為libc.so.6,線程pthread動(dòng)態(tài)鏈接庫(kù)的名字為libpthread.so.0等等.本文例子所生成的動(dòng)態(tài)鏈接庫(kù)的名字為libmy.so,雖沒(méi)有版本號(hào),但也符合所要求的格式. 生成該動(dòng)態(tài)鏈接庫(kù)的維護(hù)文件makefile-lib內(nèi)容如下: 1 # makefile : 縱橫軟件制作中心雨亦奇編寫(xiě), 2002-03-07. 2 3 all : libmy.so 4 5 SRC = getdate.c get

31、time.c 6 7 TGT = $(SRC:.c=.o) 8 9 $(SRC) : adatetime.h 10 touch $ 11 12 %.o : %.c 13 cc -c $? 14 15 # 動(dòng)態(tài)鏈接庫(kù)(libmy.so)生成 16 libmy.so : $(TGT) 17 cc -s -shared -o $ $(TGT) 18 運(yùn)行命令: $ make -f makefile-lib $ 即生成libmy.so庫(kù). 注: 維護(hù)文件中,第17行用-shared選項(xiàng)以生成動(dòng)態(tài)鏈接庫(kù),用-s選項(xiàng)以去掉目標(biāo)文件中的符號(hào)表,從而減小文件長(zhǎng)度. 三、共享動(dòng)態(tài)鏈接庫(kù) 3.1 動(dòng)態(tài)鏈接庫(kù)配置文

32、件 為了讓動(dòng)態(tài)鏈接庫(kù)為系統(tǒng)所使用,需要維護(hù)動(dòng)態(tài)鏈接庫(kù)的配置文件-/etc/ld.so.conf.此文件內(nèi),存放著可被LINUX共享的動(dòng)態(tài)鏈接庫(kù)所在目錄的名字(系統(tǒng)目錄/lib,/usr/lib除外),各個(gè)目錄名間以空白字符(空格,換行等)或冒號(hào)或逗號(hào)分隔.一般的LINUX發(fā)行版中,此文件均含一個(gè)共享目錄/usr/X11R6/lib,為X window窗口系統(tǒng)的動(dòng)態(tài)鏈接庫(kù)所在的目錄. 下面看看我的系統(tǒng)中此文件的內(nèi)容如何: # cat /etc/ld.so.conf /usr/X11R6/lib /usr/zzz/lib # 由上可以看出,該動(dòng)態(tài)庫(kù)配置文件中,增加了一個(gè)/usr/zzz/lib目錄

33、.這是我自己新建的共享庫(kù)目錄,下面存放我新開(kāi)發(fā)的可供系統(tǒng)共享的動(dòng)態(tài)鏈接庫(kù). 3.2 動(dòng)態(tài)鏈接庫(kù)管理命令 為了讓動(dòng)態(tài)鏈接庫(kù)為系統(tǒng)所共享,還需運(yùn)行動(dòng)態(tài)鏈接庫(kù)的管理命令-ldconfig.此執(zhí)行程序存放在/sbin目錄下. ldconfig命令的用途,主要是在默認(rèn)搜尋目錄(/lib和/usr/lib)以及動(dòng)態(tài)庫(kù)配置文件/etc/ld.so.conf內(nèi)所列的目錄下,搜索出可共享的動(dòng)態(tài)鏈接庫(kù)(格式如前介紹,lib*.so*),進(jìn)而創(chuàng)建出動(dòng)態(tài)裝入程序(ld.so)所需的連接和緩存文件.緩存文件默認(rèn)為/etc/ld.so.cache,此文件保存已排好序的動(dòng)態(tài)鏈接庫(kù)名字列表. ldconfig通常在系統(tǒng)啟動(dòng)時(shí)

34、運(yùn)行,而當(dāng)用戶安裝了一個(gè)新的動(dòng)態(tài)鏈接庫(kù)時(shí),就需要手工運(yùn)行這個(gè)命令. ldconfig命令行用法如下: ldconfig -v|-verbose -n -N -X -f CONF -C CACHE -r ROOT -l -p|-print-cache -c FORMAT -format=FORMAT -V -?|-help|-usage path. ldconfig可用的選項(xiàng)說(shuō)明如下: (1) -v或-verbose : 用此選項(xiàng)時(shí),ldconfig將顯示正在掃描的目錄及搜索到的動(dòng)態(tài)鏈接庫(kù),還有它所創(chuàng)建的連接的名字. (2) -n : 用此選項(xiàng)時(shí),ldconfig僅掃描命令行指定的目錄,不掃描默

35、認(rèn)目錄(/lib,/usr/lib),也不掃描配置文件/etc/ld.so.conf所列的目錄. (3) -N : 此選項(xiàng)指示ldconfig不重建緩存文件(/etc/ld.so.cache).若未用-X選項(xiàng),ldconfig照常更新文件的連接. (4) -X : 此選項(xiàng)指示ldconfig不更新文件的連接.若未用-N選項(xiàng),則緩存文件正常更新. (5) -f CONF : 此選項(xiàng)指定動(dòng)態(tài)鏈接庫(kù)的配置文件為CONF,系統(tǒng)默認(rèn)為/etc/ld.so.conf. (6) -C CACHE : 此選項(xiàng)指定生成的緩存文件為CACHE,系統(tǒng)默認(rèn)的是/etc/ld.so.cache,此文件存放已排好序的可共

36、享的動(dòng)態(tài)鏈接庫(kù)的列表. (7) -r ROOT : 此選項(xiàng)改變應(yīng)用程序的根目錄為ROOT(是調(diào)用chroot函數(shù)實(shí)現(xiàn)的).選擇此項(xiàng)時(shí),系統(tǒng)默認(rèn)的配置文件/etc/ld.so.conf,實(shí)際對(duì)應(yīng)的為ROOT/etc/ld.so.conf.如用-r /usr/zzz時(shí),打開(kāi)配置文件/etc/ld.so.conf時(shí),實(shí)際打開(kāi)的是/usr/zzz/etc/ld.so.conf文件.用此選項(xiàng),可以大大增加動(dòng)態(tài)鏈接庫(kù)管理的靈活性. 通常情況下,ldconfig搜索動(dòng)態(tài)鏈接庫(kù)時(shí)將自動(dòng)建立動(dòng)態(tài)鏈接庫(kù)的連接.選擇此項(xiàng)時(shí),將進(jìn)入專家模式,需要手工設(shè)置連接.一般用戶不用此項(xiàng). (9) -p或-print-cache

37、 : 此選項(xiàng)指示ldconfig打印出當(dāng)前緩存文件所保存的所有共享庫(kù)的名字. (10) -c FORMAT 或 -format=FORMAT : 此選項(xiàng)用于指定緩存文件所使用的格式,共有三種:old(老格式),new(新格式)和compat(兼容格式,此為默認(rèn)格式). (11) -V : 此選項(xiàng)打印出ldconfig的版本信息,而后退出. (12) -? 或 -help 或 -usage : 這三個(gè)選項(xiàng)作用相同,都是讓ldconfig打印出其幫助信息,而后退出. 舉三個(gè)例子: 例1: # ldconfig -p 793 libs found in cache /etc/ld.so.cache&

38、#39; libzvt.so.2 (libc6) => /usr/lib/libzvt.so.2 libzvt.so (libc6) => /usr/lib/libzvt.so libz.so.1.1.3 (libc6) => /usr/lib/libz.so.1.1.3 libz.so.1 (libc6) => /lib/libz.so.1 . # 注: 有時(shí)候用戶想知道系統(tǒng)中有哪些動(dòng)態(tài)鏈接庫(kù),或者想知道系統(tǒng)中有沒(méi)有某個(gè)動(dòng)態(tài)鏈接庫(kù),這時(shí),可用-p選項(xiàng)讓ldconfig輸出緩存文件中的動(dòng)態(tài)鏈接庫(kù)列表,從而查詢得到.例子中,ldconfig命令的輸出結(jié)果第1行表明在緩存文

39、件/etc/ld.so.cache中找到793個(gè)共享庫(kù),第2行開(kāi)始便是一系列共享庫(kù)的名字及其全名(絕對(duì)路徑).因?yàn)閷?shí)際輸出結(jié)果太多,為節(jié)省篇幅,以.表示省略的部分. 例2: # ldconfig -v /lib: liby.so.1 -> liby.so.1 libnss_wins.so -> libnss_wins.so . /usr/lib: libjscript.so.2 -> libjscript.so.2.0.0 libkspell.so.2 -> libkspell.so.2.0.0 . /usr/X11R6/lib: libmej-0.8.10.so -&

40、gt; libmej-0.8.10.so libXaw3d.so.7 -> libXaw3d.so.7.0 . # 注: ldconfig命令在運(yùn)行正常的情況下,默認(rèn)不輸出什么東西.本例中用了-v選項(xiàng),以使ldconfig在運(yùn)行時(shí)輸出正在掃描的目錄及搜索到的共享庫(kù),用戶可以清楚地看到運(yùn)行的結(jié)果.執(zhí)行結(jié)束后,ldconfig將刷新緩存文件/etc/ld.so.cache. 例3: # ldconfig /usr/zhsoft/lib # 注: 當(dāng)用戶在某個(gè)目錄下面創(chuàng)建或拷貝了一個(gè)動(dòng)態(tài)鏈接庫(kù),若想使其被系統(tǒng)共享,可以執(zhí)行一下"ldconfig 目錄名"這個(gè)命令.此命令的功

41、能在于讓ldconfig將指定目錄下的動(dòng)態(tài)鏈接庫(kù)被系統(tǒng)共享起來(lái),意即:在緩存文件/etc/ld.so.cache中追加進(jìn)指定目錄下的共享庫(kù).本例讓系統(tǒng)共享了/usr/zhsoft/lib目錄下的動(dòng)態(tài)鏈接庫(kù).需要說(shuō)明的是,如果此目錄不在/lib,/usr/lib及/etc/ld.so.conf文件所列的目錄里面,則再度運(yùn)行l(wèi)dconfig時(shí),此目錄下的動(dòng)態(tài)鏈接庫(kù)可能不被系統(tǒng)共享了. 3.3 動(dòng)態(tài)鏈接庫(kù)如何共享 了解了以上知識(shí),我們可以采用以下三種方法來(lái)共享動(dòng)態(tài)鏈接庫(kù)注:均須在超級(jí)用戶狀態(tài)下操作,以我的動(dòng)態(tài)鏈接庫(kù)libmy.so共享過(guò)程為例) (1)拷貝動(dòng)態(tài)鏈接庫(kù)到系統(tǒng)共享目錄下,或在系統(tǒng)共享目錄

42、下為該動(dòng)態(tài)鏈接庫(kù)建立個(gè)連接(硬連接或符號(hào)連接均可,常用符號(hào)連接).這里說(shuō)的系統(tǒng)共享目錄,指的是LINUX動(dòng)態(tài)鏈接庫(kù)存放的目錄,它包含/lib,/usr/lib以及/etc/ld.so.conf文件內(nèi)所列的一系列目錄. # cp libmy.so /lib # ldconfig # 或: # ln -s pwd/libmy.so /lib # ldconfig # (2)將動(dòng)態(tài)鏈接庫(kù)所在目錄名追加到動(dòng)態(tài)鏈接庫(kù)配置文件/etc/ld.so.conf中. # pwd >> /etc/ld.so.conf # ldconfig # (3)利用動(dòng)態(tài)鏈接庫(kù)管理命令ldconfig,強(qiáng)制其搜索指

43、定目錄,并更新緩存文件,便于動(dòng)態(tài)裝入. # ldconfig pwd # 需要說(shuō)明的是,這種操作方法雖然有效,但效果是暫時(shí)的,供程序測(cè)試還可以,一旦再度運(yùn)行l(wèi)dconfig,則緩存文件內(nèi)容可能改變,所需的動(dòng)態(tài)鏈接庫(kù)可能不被系統(tǒng)共享了.與之相比較,前兩種方法是可靠的方法,值得業(yè)已定型的動(dòng)態(tài)鏈接庫(kù)共享時(shí)采用.前兩種方法還有一個(gè)特點(diǎn),即最后一條命令都是ldconfig,也即均需要更新一下緩存文件,以確保動(dòng)態(tài)鏈接庫(kù)的共享生效. 四、含有動(dòng)態(tài)函數(shù)的程序的編譯 4.1 防止編譯因未指定動(dòng)態(tài)鏈接庫(kù)而出錯(cuò) 當(dāng)一個(gè)程序使用動(dòng)態(tài)函數(shù)時(shí),編譯該程序時(shí)就必須指定含所用動(dòng)態(tài)函數(shù)的動(dòng)態(tài)鏈接庫(kù),否則編譯將會(huì)出錯(cuò)退出.如本文

44、示例程序ady.c的編譯(未明確引用動(dòng)態(tài)鏈接庫(kù)libmy.so): # cc -o ady ady.c /tmp/ccL4FsJp.o: In function main': /tmp/ccL4FsJp.o(.text+0x43): undefined reference to gettime' collect2: ld returned 1 exit status # 注: 因?yàn)閍dy.c所含的動(dòng)態(tài)函數(shù)getdate,gettime不在系統(tǒng)函數(shù)庫(kù)中,所以連接時(shí)出錯(cuò). 4.2 編譯時(shí)引用動(dòng)態(tài)鏈接庫(kù)的幾種方式 (1)當(dāng)所用的動(dòng)態(tài)鏈接庫(kù)在系統(tǒng)目錄(/lib,/usr/lib)下時(shí),

45、可用編譯選項(xiàng)-l來(lái)引用.即: # cc -lmy -o ady ady.c # 注:編譯時(shí)用-l選項(xiàng)引用動(dòng)態(tài)鏈接庫(kù)時(shí),庫(kù)名須使用其縮寫(xiě)形式.本例的my,表示引用libmy.so庫(kù).若引用光標(biāo)庫(kù)libncurses.so,須用-lncurses.注意,-l選項(xiàng)與參數(shù)之間不能有空格,否則會(huì)出錯(cuò). (2)當(dāng)所用的動(dòng)態(tài)鏈接庫(kù)在系統(tǒng)目錄(/lib,/usr/lib)以外的目錄時(shí),須用編譯選項(xiàng)-L來(lái)指定動(dòng)態(tài)鏈接庫(kù)所在的目錄(供編譯器查找用),同時(shí)用-l選項(xiàng)指定縮寫(xiě)的動(dòng)態(tài)鏈接庫(kù)名.即: # cc -L/usr/zzz/lib -lmy -o ady ady.c # (3)直接引用所需的動(dòng)態(tài)鏈接庫(kù).即: #

46、cc -o ady ady.c libmy.so # 或 # cc -o ady ady.c /lib/libmy.so # 等等.其中,動(dòng)態(tài)鏈接庫(kù)的庫(kù)名可以采用相對(duì)路徑形式(文件名不以/開(kāi)頭),也可采用絕對(duì)路徑形式(文件名以/開(kāi)頭). 五、動(dòng)態(tài)鏈接程序的運(yùn)行與檢查 5.1 運(yùn)行 編譯連接好含動(dòng)態(tài)函數(shù)的程序后,就可以運(yùn)行它了.動(dòng)態(tài)鏈接程序因?yàn)楣蚕砹讼到y(tǒng)中的動(dòng)態(tài)鏈接庫(kù),所以其空間占用很小.但這并不意味功能的減少,它的執(zhí)行與靜態(tài)連接的程序執(zhí)行,效果完全相同.在命令提示符下鍵入程序名及相關(guān)參數(shù)后回車(chē)即可,如下例: $ ady 動(dòng)態(tài)鏈接庫(kù)高級(jí)應(yīng)用示范 當(dāng)前日期: 2002-03-11 當(dāng)前時(shí)間: 19:39:06 $ 5.2 檢查 檢查什么?檢查動(dòng)態(tài)鏈接程序究竟需要哪些共享庫(kù),系統(tǒng)中是否已有這些庫(kù),沒(méi)有的話,用戶好想辦法把這些庫(kù)裝上. 怎么檢查呢?這里,告訴你一個(gè)實(shí)用程序-ldd,這個(gè)程序就是專門(mén)用來(lái)檢查動(dòng)態(tài)鏈接程序依賴哪些共享庫(kù)的. ldd命令行用法如下: ldd -version -v|-verbose -d|-data-relocs -r|-function-relocs -help FILE.

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論