文章目录

  • 1.linux下查找库文件所在位置
  • 2.如何查看库里面包含的函数
  • 3.烦人的undefined reference to
  • 4.gcc "undefined reference to" 问题解决方法
  • 5.Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别

1.linux下查找库文件所在位置

ldconfig -p | grep libcrypto
  • glibc的库版本号查询
因为ldd命令也是glibc提供的,所以也能查看

ldd  --version

2.如何查看库里面包含的函数

  • 使用linux系统的nm命令。很简单。在我用的时候遇到了一个问题:
(1)例如nm lib_a.so。
因此输入如下命令:
nm -Do lib_a.so
便可以看到里面的库函数了。

(2)nm libyolo.so | grep 'compute_box_iou'
  U compute_box_iou
注意:U的意思本身就是undefined未定义的意思

说明:
(1)此处的.so文件时动态链接库文件。该文件时elf(Executable and Linkable Format)文件的一种,有两个符号表,“.symtab”和“.dynsym”。
(2)查看动态符号表“.dynsym”,加上-D选项;
(3)“.dynsym”只保留“.symtab”中的全局符号(global symbols);
(4)nm lib_a.so查看的“.symtab”的符号表
  • ldd+可执行文件,ldd+so库
(1)
#ldd main
linux-gate.so.1 => (0xb809c000)
libc.so.6 +> /lib/tls/i686/cmov/libc.so,6 (0x7f0c000)

(2)
# ldd   /usr/lib/aarch64-linux-gnu/libSM.so
linux-vdso.so.1 =>  (0x0000ffffb1b70000)
libICE.so.6 => /usr/lib/aarch64-linux-gnu/libICE.so.6 (0x0000ffffb1ae0000)
libuuid.so.1 => /lib/aarch64-linux-gnu/libuuid.so.1 (0x0000ffffb1ac0000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffb1970000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffb1b80000)

3.烦人的undefined reference to

  • 注意思想:
这是下面的guard macro用错所致!
#ifndef ZW_STACK_ARRAY
#define ZW_STACK_ARRAY
由于zwlist.h中这个宏已经被定义,当你在zwlist.c包含zwlist.h之后,
#ifndef ZW_STACK_ARRAY已经不成立,所有的zwlist.c中的代码都被直接忽略

4.gcc “undefined reference to” 问题解决方法

  • (1)链接时缺失了相关目标文件(.o)
    测试代码如下:

    然后编译。
gcc -c test.c  
gcc –c main.c 
得到两个 .o 文件,一个是 main.o,一个是 test.o ,然后我们链接 .o 得到可执行程序:

gcc -o main main.o 
这时,你会发现,报错了:

main.o: In function `main':  
main.c:(.text+0x7): undefined reference to `test'  
collect2: ld returned 1 exit status 
这就是最典型的undefined reference错误,因为在链接时发现找不到某个函数的实现文件,本例中test.o文件中包含了test()函数的实现,
所以如果按下面这种方式链接就没事了。
gcc -o main main.o test.o
  • (2)链接时缺少相关的库文件(.a/.so)
先把test.c编译成静态库(.a)文件

gcc -c test.c  
ar -rcs test.a test.o 
至此,我们得到了test.a文件。我们开始编译main.c

gcc -c main.c 
这时,则生成了main.o文件,然后我们再通过如下命令进行链接希望得到可执行程序。

gcc -o main main.o 
你会发现,编译器报错了:

/tmp/ccCPA13l.o: In function `main':  
main.c:(.text+0x7): undefined reference to `test'  
collect2: ld returned 1 exit status 
其根本原因也是找不到test()函数的实现文件,由于该test()函数的实现在test.a这个静态库中的,
故在链接的时候需要在其后加入test.a这个库,链接命令修改为如下形式即可。
gcc -o main main.o ./test.a  //注:./ 是给出了test.a的路径
  • (3)链接的库文件中又使用了另一个库文件
从上图可以看出,main.c调用了test.c的函数,test.c中又调用了fun.c的函数。
首先,我们先对fun.c,test.c,main.c进行编译,生成 .o文件。

gcc -c func.c  
gcc -c test.c  
gcc -c main.c 
然后,将test.c和func.c各自打包成为静态库文件。

ar –rc func.a func.o  
ar –rc test.a test.o 
这时,我们准备将main.o链接为可执行程序,由于我们的main.c中包含了对test()的调用,
因此,应该在链接时将test.a作为我们的库文件,链接命令如下。
gcc -o main main.o test.a 
这时,编译器仍然会报错,如下:
test.a(test.o): In function `test':  
test.c:(.text+0x13): undefined reference to `func'  
collect2: ld returned 1 exit status 

就是说,链接的时候,发现我们的test.a调用了func()函数,找不到对应的实现。
由此我们发现,原来我们还需要将test.a所引用到的库文件也加进来才能成功链接,因此命令如下。
gcc -o main main.o test.a func.a
  • (4)多个库文件链接顺序问题
这种问题也非常的隐蔽,不仔细研究你可能会感到非常地莫名其妙。
 我们依然回到第(3)小节所讨论的问题中,在最后,如果我们把链接的库的顺序换一下,看看会发生什么结果?

gcc -o main main.o func.a test.a 
 我们会得到如下报错.
test.a(test.o): In function `test':  
test.c:(.text+0x13): undefined reference to `func'  
collect2: ld returned 1 exit status 

因此,我们需要注意,在链接命令中给出所依赖的库时,需要注意库之间的依赖顺序,
依赖其他库的库一定要放到被依赖库的前面,这样才能真正避免undefined reference的错误,完成编译链接。
越是调用别人的越上层的库,就越放在前面。
  • (5)在c++代码中链接c语言的库
如果你的库文件由c代码生成的,则在c++代码中链接库中的函数时,也会碰到undefined reference的问题。
下面举例说明。
首先,编写c语言版库文件: 
编译,打包为静态库:test.a

gcc -c test.c  
ar -rcs test.a test.o 
至此,我们得到了test.a文件。下面我们开始编写c++文件main.cpp

gcc “undefined reference to“ 问题解决方法_库文件

然后编译main.cpp生成可执行程序:
g++ -o main main.cpp test.a 
会发现报错:
/tmp/ccJjiCoS.o: In function `main': 
main.cpp:(.text+0x7): undefined reference to `test()' 
collect2: ld returned 1 exit status 

原因就是main.cpp为c++代码,调用了c语言库的函数,因此链接的时候找不到.
解决方法:即在main.cpp中,把与c语言库test.a相关的头文件包含添加一个extern "C"的声明即可。
例如,修改后的main.cpp如下:

gcc “undefined reference to“ 问题解决方法_动态库_02

g++ -o main main.cpp test.a 
再编译会发现,问题已经成功解决。

5.Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别

  • Linux gcc编译时,的动态库搜索路径动态库的搜索路径顺序如下(注意不会递归性地在其子目录下搜索):
1、gcc编译、链接命令中的-L选项;
2、gcc的环境变量的LIBRARY_PATH(多个路径用冒号分割);
3、gcc默认动态库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib。
  • Linux gcc链接时,为了生成可执行二进制文件,动态库搜索路径如下:
1、编译目标代码时指定的动态库搜索路径:用选项-Wl,rpath和include指定的动态库的搜索路径,比如gcc -Wl,
-rpath,include -L. -ldltest hello.c,在执行文件时会搜索路径`./include`;
2、环境变量LD_LIBRARY_PATH(多个路径用冒号分割);
3、在 /etc/ld.so.conf.d/ 目录下的配置文件指定的动态库绝对路径(通过ldconfig生效,一般是非root用户时使用);
4、gcc默认动态库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib等。
  • 参考:
gcc "undefined reference to" 问题解决方法


C++ 使用动态链接库xx.so 时出现undefined reference错误


烦人的undefined reference to... 
linux下查找库文件所在位置
"undefined reference to" 问题解决方法
如查看库里面包含的函数
"undefined reference to" 问题汇总及解决方法

gcc 库的链接顺序问题
Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别