最近在將我們的工程切換到cmake工具構建,遇到了乙個由於鏈結順序引起的問題,當時沒看出來原因,被困擾了幾個小時,特此記錄一下。
編譯報錯類似下面這樣,提示在libsum.a庫中sum函式找不到add的定義。
/usr/bin/ld: libsum.a(sum.o): in function `sum':
sum.c:(.text+0x1d): undefined reference to `add'
collect2: error: ld returned 1 exit status
怎麼會沒找到呢?我明明鏈結了libadd.a呀,難道庫有問題。
通過nm命令檢視libadd.a中的符號,如下。
add.o:
0000000000000000 t add
有add啊,但是符號值怎麼是全0?沒有寫實現嗎?
於是去看原始檔,發現其實是有實現的。
那麼問題出在**呢?
這時候乙個聲音響起,「會不會是鏈結順序不對?」,真可謂一語驚醒夢中人。
馬上把libsum.a和libadd.a的鏈結順序對換,問題果然解決了。
(其實,當時沒想起來這個原因,也是因為在切換cmake之前,這個鏈結順序也能通過編譯。很奇怪,還需要再深入看看。)
通過報錯,基本就可以看出來了,在libsum.a中使用了libadd.a中的符號,那麼鏈結時需要將libsum.a放前面,libadd.a放後面。
這個是由編譯器決定的,對於gcc來說,libsum.a放前面,libadd.a放後面,當找不到libsum.a中的符號時,它會在後面的鏈結庫中繼續查詢。
大家可以自己試試,這裡提供原始檔和編譯命令。
add.h
#
ifndef
__add_h__
#define
__add_h__
intadd
(int a,
int b);#
endif
add.c
#
include
"add.h"
intadd
(int a,
int b)
sum.h
#
ifndef
__sum_h__
#define
__sum_h__
intsum
(int a,
int b);#
endif
sum.c
#
include
"add.h"
#include
"sum.h"
intsum
(int a,
int b)
main.c
#
include
"sum.h"
#include
intmain()
首先生成add靜態庫
gcc -c add.c -o add.o
ar -rc libadd.a add.o
然後生成sum靜態庫
gcc -c sum.c -o sum.o
ar -rc libsum.a sum.o
編譯main.c(鏈結順序不對)
gcc main.c libadd.a libsum.a -o main
解決由於意外斷電引起的活動目錄服務停止問題
背景 位於集團b座的機房已經使用多年,很多硬體條件開始制約公司it的發展。6月中旬一天,由於機房空調進行維修,工人師傅冒然拉斷了電源總閘,導致機房內部分伺服器意外斷電。集團總部的兩台用活動目錄域控制器也不幸遇難。現象 負責機房的工程師在第一時間進行了及時的處理。恢復供電之後馬上啟動因斷電而停止的伺服...
解決由於意外斷電引起的活動目錄服務停止問題
背景 位於集團b座的機房已經使用多年,很多硬體條件開始制約公司it的發展。6月中旬一天,由於機房空調進行維修,工人師傅冒然拉斷了電源總閘,導致機房內部分伺服器意外斷電。集團總部的兩台用活動目錄域控制器也不幸遇難。現象 負責機房的工程師在第一時間進行了及時的處理。恢復供電之後馬上啟動因斷電而停止的伺服...
順序執行命令需要哪個符號鏈結 搭建自己的符號伺服器
看雪論壇作者id comor 注意 如果你要找的是微軟符號伺服器,不用往下看了 當發生應用異常崩潰 驅動藍屏時,無論是測試環境,還是生產環境,分析dump檔案通常是快速定位問題的乙個最佳選擇 前提是生成了dump檔案 特別是在生產環境時,既沒有原始碼又沒有偵錯程式,這時只有將日誌檔案 dump檔案拷...