qqwx

导航

库文件的使用

背景:

初学者经常搞不清楚,一个main.cpp文件,调用了某库(可能静态也可动态)中的函数,如何将它跑起来。

 

编译:

g++ -c main.cpp
main.cpp:3:26: fatal error: leveldb/db.h: No such file or directory
 #include "leveldb/db.h"
                          ^
compilation terminated.
缺少头文件,加上再编译(编译只与头文件有关,不需要关注库):
g++ -c main.cpp -I/home/ww/2.src/leveldb/include

 

OK,生成main.o
 
链接:
  • 先考虑链接静态库的情况(同时存在动态和静态库的情况下,默认使用静态库)。
g++ -o main main.o -L/home/ww/2.src/leveldb/out-static -lleveldb -lpthread

OK,执行正常。

 

  • 如果是动态库的链接,链接方法是一样:
g++ -o main main.o -L/home/ww/2.src/leveldb/out-shared -lleveldb -lpthread

但这个可执行文件是跑不了的:

ldd main
        linux-vdso.so.1 (0x00007fffd58f2000)
        libleveldb.so.1 => not found
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fbb4a509000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fbb4a1fe000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbb49efd000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fbb49ce7000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbb4993c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fbb4a726000)

./main
./main: error while loading shared libraries: libleveldb.so.1: cannot open shared object file: No such file or directory

 

因为动态库不仅在编译(具体来看是链接)时要被搜索,在二进制文件加载和执行时也要搜索。上面的例子仅指定了链接时的搜索。
 
看下文档对于动态库的说明:
linux程序跑时,program loader会自动被加载并跑起来(即上面加红的/lib64/ld-linux-x86-64.so.2 (0x00007ff40629d000) )。它作用是找到当前程序依赖的各个库文件,并加载它们。

 

loader找到动态库文件有几种方法:

  1. ldconfig
这是最正式的方法,正式发布都应该使用这种方法。
默认的loader搜索动态库的路径在 /etc/ld.so.conf定义。
如:
ww@iZj6c1oc6sq0uze89upki0Z:/etc/ld.so.conf.d$ cat *
/usr/lib/x86_64-linux-gnu/libfakeroot
# libc default configuration
/usr/local/lib
# Multiarch support
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu

因此,需要将动态库放到对应的地点,并对应修改或增加.conf文件。

 

之后,需要调用ldconfig。它的作用是建立起加载所需要的符号缓存。这里不做示例。

 

  1. prelaod
这种方式适用于需要部分替换已有库文件中的一些方法。当然也能作为加载路径使用。具体使用是使用LD_PRELOAD环境变量:
LD_PRELOAD=/home/ww/2.src/leveldb/out-shared/libleveldb.so ./main
Open db OK
  1. LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/home/ww/2.src/leveldb/out-shared:${LD_LIBRARY_PATH}

ldd main
        linux-vdso.so.1 (0x00007ffe239f5000)
        libleveldb.so.1 => /home/ww/2.src/leveldb/out-shared/libleveldb.so.1 (0x00007ff405fe6000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff405dc9000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff405abe000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff4057bd000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff4055a7000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff4051fc000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ff40629d000)
调试时用此方法比较方便,正式场合也可用。但它有一些潜在的问题:
- 由于安全原因,在使用setuid的情况下不会生效。具体见参考文献。
 
  1. 直接使用loader指定路径调用
/lib64/ld-linux-x86-64.so.2 --library-path /home/ww/2.src/leveldb/out-shared ./main
Open db OK
调试使用。

 

 

参考:

【1】http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

【2】http://xahlee.info/UnixResource_dir/_/ldpath.html

 

 

 
 
 
 
 

posted on 2017-01-17 01:26  qqwx  阅读(1059)  评论(0编辑  收藏  举报