2009-06-03 108 views
2

我遇到鏈接問題。我需要鏈接到共享庫libfoo.so,這取決於函數read,我想在read.c文件中定義自己。nm報告符號已定義,但ldd報告符號未定義

我編譯和鏈接在一起的一切,但在運行時出現錯誤

/home/bar/src/libfoo.so: undefined symbol: sread. 

納米報告符號被定義

$nm baz | grep sread 
    00000000000022f8 t sread 

但LDD報告symbol未定義

$ldd -r baz | grep sread 
undefined symbol: sread (/home/bar/src/libfoo.so) 

什麼給了? libfoo.so是一個共享庫嗎?

+0

也許你應該發佈所有共享對象和可執行文件的完整鏈接線,以闡明這個主題。 – lothar 2009-06-03 05:46:08

回答

13

首先,定義一個名爲'read'的函數是一個壞主意(TM),因爲它是所有UNIXen上的標準libc函數。當你這樣做時,你的程序的行爲是不確定的。

其次,您在libbaz.so中定義的read函數在nm輸出中標有't'。這意味着這個功能是本地的(libbaz.so以外不可見)。全球功能用'T'nm標記。

當您在read.c中定義它時,是否使用了'static int read(...)'? 如果不是,那麼在編譯和鏈接libbaz.so時,是否在命令行上使用鏈接描述文件或attribute((visibility(hidden)))-fvisibility=hidden

-1

當您構建共享庫時,您需要從同一個庫或另一個(共享)庫中解析未定義的符號全部。鏈接器將而不是從您的應用程序的符號庫中解析未定義的符號。

+0

我應該說明baz實際上是一個共享庫。那麼這是否意味着我應該創建一個僅包含讀取函數的共享庫,並鏈接到這個庫?有沒有一種明確的方式告訴鏈接器使用這個其他共享庫(比如說libread.so)來解析來自共享庫libfoo.so的未定義符號? – codehippo 2009-06-03 04:16:09

+2

你完全搞錯了:運行時加載程序會高興地從共享庫中解析未定義的符號,只要符號在其動態表中被「導出」(這發生在例如當可執行文件與-rdynamic鏈接時) 。 – 2009-06-03 05:06:29

1

當使用G ++編譯C代碼,然後進行鏈接時,上述錯誤也會發生。 G ++執行名稱修改,因此實際符號可能與「_Zsds_ [function_name] _」類似,導致鏈接器在搜索未被修改的名稱時會窒息。

今天我遇到了相同的行爲,除了我的問題在Wikipedia上列出的操作後解決。基本上,用C++編譯器編譯的C代碼在符號表中會有一個「錯位」的名稱,導致C樣式符號解析失敗。