1. 程式人生 > >Linux 編譯報錯 -- undefined reference to 問題解決方法 (具體'pthread_create'和opencv看文章最後兩條)

Linux 編譯報錯 -- undefined reference to 問題解決方法 (具體'pthread_create'和opencv看文章最後兩條)

最近在Linux下程式設計發現一個詭異的現象,就是在連結一個靜態庫的時候總是報錯,類似下面這樣的錯誤:
  1. (.text+0x13): undefined reference to `func'

    關於undefined reference這樣的問題,大家其實經常會遇到,在此,我以詳細地示例給出常見錯誤的各種原因以及解決方法,希望對初學者有所幫助。

(ps,1-5是針對自定義的函式,6針對執行緒,7針對opencv)

1.  連結時缺失了相關目標檔案(.o)

測試程式碼如下:

    然後編譯。

  1. gcc -c test.c
  2. gcc –c main.c

    得到兩個 .o 檔案,一個是 main.o,一個是 test.o ,然後我們連結 .o 得到可執行程式:

gcc -o main main.o

    這時,你會發現,報錯了:

  1. main.o: In function `main':
  2. main.c:(.text+0x7): undefined reference to `test'
  3. collect2: ld returned 1 exit status

    這就是最典型的undefined reference錯誤,因為在連結時發現找不到某個函式的實現檔案,本例中test.o檔案中包含了test()函式的實現,所以如果按下面這種方式連結就沒事了。

  1. gcc -o main main.o test.o

   【擴充套件】:其實上面為了讓大家更加清楚底層原因,我把編譯連結分開了,下面這樣編譯也會報undefined reference錯,其實底層原因與上面是一樣的。

  1. gcc -o main main.c //缺少test()的實現檔案

需要改成如下形式才能成功,將test()函式的實現檔案一起編譯。

  1. gcc -o main main.c test.c //ok,沒問題了

2.    連結時缺少相關的庫檔案(.a/.so)

    在此,只舉個靜態庫的例子,假設原始碼如下。

    先把test.c編譯成靜態庫(.a)檔案

  1. gcc -c test.c
  2. ar -rc test.a test.o

    至此,我們得到了test.a檔案。我們開始編譯main.c

  1. gcc -c main.c

    這時,則生成了main.o檔案,然後我們再通過如下命令進行連結希望得到可執行程式。

  1. gcc -o main main.o

    你會發現,編譯器報錯了:

  1. /tmp/ccCPA13l.o: In function `main':
  2. main.c:(.text+0x7): undefined reference to `test'
  3. collect2: ld returned 1 exit status

    其根本原因也是找不到test()函式的實現檔案,由於該test()函式的實現在test.a這個靜態庫中的,故在連結的時候需要在其後加入test.a這個庫,連結命令修改為如下形式即可。

  1. gcc -o main main.o ./test.a //注:./ 是給出了test.a的路徑

     【擴充套件】:同樣,為了把問題說清楚,上面我們把程式碼的編譯連結分開了,如果希望一次性生成可執行程式,則可以對main.c和test.a執行如下命令。

  1. gcc -o main main.c ./test.a //同樣,如果不加test.a也會報錯

3.    連結的庫檔案中又使用了另一個庫檔案

    這種問題比較隱蔽,也是我最近遇到的與網上大家討論的不同的問題,舉例說明如下,首先,還是看看測試程式碼。

    從上圖可以看出,main.c呼叫了test.c的函式,test.c中又呼叫了fun.c的函式。
    首先,我們先對fun.c,test.c,main.c進行編譯,生成 .o檔案。

  1. gcc -c func.c
  2. gcc -c test.c
  3. gcc -c main.c

    然後,將test.c和func.c各自打包成為靜態庫檔案。

  1. ar –rc func.a func.o
  2. ar –rc test.a test.o

    這時,我們準備將main.o連結為可執行程式,由於我們的main.c中包含了對test()的呼叫,因此,應該在連結時將test.a作為我們的庫檔案,連結命令如下。

  1. gcc -o main main.o test.a

    這時,編譯器仍然會報錯,如下:

  1. test.a(test.o): In function `test':
  2. test.c:(.text+0x13): undefined reference to `func'
  3. collect2: ld returned 1 exit status

    就是說,連結的時候,發現我們的test.a呼叫了func()函式,找不到對應的實現。由此我們發現,原來我們還需要將test.a所引用到的庫檔案也加進來才能成功連結,因此命令如下。

  1. gcc -o main main.o test.a func.a

    ok,這樣就可以成功得到最終的程式了。同樣,如果我們的庫或者程式中引用了第三方庫(如pthread.a)則同樣在連結的時候需要給出第三方庫的路徑和庫檔案,否則就會得到undefined reference的錯誤。

4 多個庫檔案連結順序問題

    這種問題也非常的隱蔽,不仔細研究你可能會感到非常地莫名其妙。我們依然回到第3小節所討論的問題中,在最後,如果我們把連結的庫的順序換一下,看看會發生什麼結果?

  1. gcc -o main main.o func.a test.a

    我們會得到如下報錯.

  1. test.a(test.o): In function `test':
  2. test.c:(.text+0x13): undefined reference to `func'
  3. collect2: ld returned 1 exit status

    因此,我們需要注意,在連結命令中給出所依賴的庫時,需要注意庫之間的依賴順序,依賴其他庫的庫一定要放到被依賴庫的前面,這樣才能真正避免undefined reference的錯誤,完成編譯連結。

5. 在c++程式碼中連結c語言的庫

    如果你的庫檔案由c程式碼生成的,則在c++程式碼中連結庫中的函式時,也會碰到undefined reference的問題。下面舉例說明。

    首先,編寫c語言版庫檔案:

   

    編譯,打包為靜態庫:test.a

  1. gcc -c test.c
  2. ar -rc test.a test.o

    至此,我們得到了test.a檔案。下面我們開始編寫c++檔案main.cpp

   

    然後編譯main.cpp生成可執行程式:

  1. g++ -o main main.cpp test.a

    會發現報錯:

  1. /tmp/ccJjiCoS.o: In function `main':
  2. main.cpp:(.text+0x7): undefined reference to `test()'
  3. collect2: ld returned 1 exit status

    原因就是main.cpp為c++程式碼,呼叫了c語言庫的函式,因此連結的時候找不到,解決方法:即在main.cpp中,把與c語言庫test.a相關的標頭檔案包含新增一個extern "C"的宣告即可。例如,修改後的main.cpp如下:

   

  1. g++ -o main main.cpp test.a

    再編譯會發現,問題已經成功解決。

6. 多執行緒程式設計中 undefined reference to 'pthread_create' / 'pthread_join':

undefined reference to 'pthread_create'
undefined reference to 'pthread_join'

問題原因:
   pthread 庫不是 Linux 系統預設的庫,連線時需要使用靜態庫 libpthread.a,所以在使用pthread_create()建立執行緒,以及呼叫 pthread_atfork()函式建立fork處理程式時,需要連結該庫。

問題解決:
    在編譯中要加 -lpthread引數
    gcc thread.c -o thread -lpthread
    thread.c為你些的原始檔,不要忘了加上標頭檔案#include<pthread.h>

 7. opencv程式設計中 undefined reference to 'cv::dft':

./obj/local/armeabi/libopencv_imgproc.a(templmatch.cpp.o):In function `cv::crossCorr(cv::Matconst&, cv::Matconst&, cv::Mat&, cv::Size_<int>,int, cv::Point_<int>,double,int)':
templmatch.cpp:(.text+0x47e): undefined reference to `cv::getOptimalDFTSize(int)'
templmatch.cpp:(.text+0x494): undefined reference to `cv::getOptimalDFTSize(int)'
templmatch.cpp:(.text+0x92c): undefined reference to `cv::dft(cv::_InputArray const&, cv::_OutputArray const&,int,int)'
templmatch.cpp:(.text+0xfa4): undefined reference to `cv::dft(cv::_InputArray const&, cv::_OutputArray const&,int,int)'
templmatch.cpp:(.text+0x1006): undefined reference to `cv::mulSpectrums(cv::_InputArray const&, cv::_InputArray const&, cv::_OutputArray const&,int,bool)'
templmatch.cpp:(.text+0x102e): undefined reference to `cv::dft(cv::_InputArray const&, cv::_OutputArray const&,int,int)'
。。。。。。
問題原因:
   連結時缺少相關的庫,或者庫新增的先後順序不滿足依賴關係。

問題解決:
    在連結中新增相關的opencv庫,比如opencv_features2d,opencv_flann,opencv_imgproc,opencv_core,opencv_highgui,opencv_calib3d等等。其次,新增的庫要按照依賴關係排序,比如opencv_imgproc依賴opencv_core,opencv_features2d依賴opencv_imgproc,所以順序就是opencv_feature2d,opencv_imgproc,opencv_core.

相關推薦

Linux 編譯 -- undefined reference to 問題解決方法 具體'pthread_create'opencv文章最後

最近在Linux下程式設計發現一個詭異的現象,就是在連結一個靜態庫的時候總是報錯,類似下面這樣的錯誤: (.text+0x13): undefined reference to `func'     關於undefined reference這樣的問題,大家其實經常會遇到

Linux 編譯 -- undefined reference to 問題解決方法 具體'pthread_create'opencv文章最後

最近在Linux下程式設計發現一個詭異的現象,就是在連結一個靜態庫的時候總是報錯,類似下面這樣的錯誤: (.text+0x13): undefined reference to `func'     關於undefined reference這樣的問題,大家其實經常會遇

Linux 編譯 undefined reference to `pthread_create'

在編譯Linux下多執行緒程式的時候出現錯誤資訊, 寫好程式碼,進行編譯時,出現如下錯誤提示資訊:  thread.c:(.text+0xae): undefined reference to `pthread_create' thread.c:(.

minigui:解決gvfb編譯undefined reference to symbol 'XkbGetIndicatorState'

minigui在linux PC平臺建立開發環境時,需要Virtual Frame Buffer 支援(gvfb,qvfb),minigui官網提供了這兩個程式的原始碼,需要自己下載編譯並安裝到自己的PC上。 我用的是gvfb,minigui下載地址:http://www.minig

Clion lua 編譯: undefined reference to `lual_newstate' 在win10上面編譯lua5.3.5以及解決方法

在CmakeLists.txt裡面新增:  ``` include_directories("D:\\lua\\lua-5.3.5\\lua-5.3.5\\dist\\include") link_directories("D:\\lua\\lua-5.3.5\\lua-5.3.5

Linux編譯程式 undefined reference to error 的解決方法

對於我這個剛入IT行業不就得新手來說,在linux下連結庫的時候總是會遇到各種各樣奇葩的問題,最多的就是“undefined reference to”和“cannot find”這兩類,層出不窮,總是在我即將完成工作的時候給我當頭一棒,讓我欲罷不能。這不,這幾天編譯linux下一個專案時又遇到難題

c++ template 多層繼承下找不到純虛擬函式實現 :undefined reference to "xxx"

如下程式碼中,定義了3個類,ClassA,ClassB,ClassC,依次為被繼承關係,ClassA,ClassB是模板類, 在ClassA中定義了一個純虛擬函式getKeyFromObject,實現將從V中獲取K的功能: getKeyFromObject函

boost log undefined reference to boost::log::v2_mt_posix::basic_formatter

在編譯boost log檔案時報錯提示: undefined reference to `boost::log::v2_mt_posix::basic_formatter<char> boost::log::v2_mt_posix::parse_formatt

Makefile編寫執行問題,undefined reference to `main'

Makefile檔案 CC=cc CFLAGS=-g -c OBJDIR=obj OBJS=func.o main_test.o go:$(OBJS:%=$(OBJDIR)/%) ${C

解決使用NDK進行編譯時出現undefined reference to function的問題

之前在編譯jni時出現了undefined reference to function這個問題,查閱相關資料說是可能連結的庫問題,然後通過各種gcc調整順序解決了這個問題。這個工程是導師的工程,工程在Linux環境下執行無誤,我從Linux環境往Android

g++編譯連結c語言檔案undefined reference ” 的處理

用QT寫一介面程式,其中用到另一同事寫的一個小功能,他是用c語言寫的,於是把他的程式碼標頭檔案和原始檔都copy過來了,加入工程中,結果連結的時候就總報錯 undefined reference 某個函式。再三確認了makefile檔案和原始碼,表示沒問題,後來想到或許是g+

「caffe編譯bug」 undefined reference to `boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::__cxx11

CXX/LD -o .build_release/tools/test_net.binCXX/LD -o .build_release/tools/convert_annoset.binCXX/LD -o .build_release/tools/device_query.binCXX/LD -o .buil

ubuntu 下 make 編譯錯誤:undefined reference to cv::line

在編譯一個專案時候出現 “undefined reference to cv::line” 的錯誤,是在連結其中一個靜態庫的時候出現的錯誤,錯誤如下: /home/build/lib/libapriltags.a(TagDetection.cc.o): In function `AprilTag

Qt 編譯出錯:undefined reference to vtable XXX

  在Qt編譯的過程中,程序會出現 error: undefined reference to `vtable for 類名'的問題,對於不經常使用QT的人來說甚是頭疼,其實這類問題發生的主要原因在於,一般我們定義了一個類以後,如果他是繼承了其他類的話 就比如說我們

編譯錯誤:undefined reference to `__umoddi3'的處理

用gcc 4.3編譯kernel 2.6.22,結果出現:undefined reference to `__umoddi3'這樣的錯誤。查google是gcc 4.3太新的問題,在更新的kernel應該沒有這個問題,解決的辦法如下:cd kernelvi Makefile找

Android Studio 3.0.1 gradle編譯 Error : unable to resolve dependency for
linux 連結 靜態庫 undefined reference to

最近將專案移植到linux上,工程需要依賴三個靜態庫:libprojcommon.a libluabind.a liblua.a 依賴關係是projcommon依賴luabind,luabind依賴lua,所以專案最終的連結引數是這樣的: -L/home/boy/ProjCommon/lib -lproj

Error:Unable to tunnel through proxy. Proxy returns "HTTP/1.1 400 Bad Request , 原因以及解決方法

Android studio出現Error:Unable to tunnel through proxy. Proxy returns "HTTP/1.1 400 Bad Request"的解決辦法原因 :AS 自帶的gradle 版本太低。 第一步: 下載對的 gredel

xilinx zynq SDK 關於編譯“dereferencing pointer to incomplete type

    轉自: https://my.oschina.net/michaelyuanyuan/blog/68203h> ... struct icmp* aaa; aaa = (struct icmp*)malloc(sizeof(struct icmp));

關於編譯“dereferencing pointer to incomplete type...

make的時候報錯:dereferencingpointer to incomplete type。 這個報錯的意思是,試圖訪問該pointer指向的變數,卻發現該變數是一個不完整的型別,多出錯於