ldd
命令的作用是打印共享库的依赖关系
ldd不是一个可执行程序,而只是一个shell脚本。ldd能够显示可执行模块的 dependency,其原理是通过设置一系列的环境变量,如下:LD_TRACE_LOADED_OBJECTS、LD_WARN、LD_BIND_NOW、LD_LIBRARY_VERSION、 LD_VERBOSE等。
ldd的工作原理,其实质是通过ld-linux.so(elf动态库的装载器)来实现的。
ld-linux.so
模块会先于executable
模块程序工作,并获得控制权,因此当上述的那些环境变量被设置时,ld-linux.so选择了显示可执行模块的dependency。
实际上可以直接执行ld-linux.so模块,如:/lib/ld-linux.so.2 --list program
(这相当于ldd program)
1 | /usr/bin/ld: skipping incompatible /home/user/lib/libtinyalsa.so when searching for -ltinyalsa |
so库的架构不匹配,可以通过file name.so
查看so库的架构,也可以使用readelf
命令查看so文件架构信息的示例: readelf -h libexample.so
。输出so文件的头部信息,其中包括Machine
字段,即架构信息。Machine字段的值对应于不同的架构,比如x86、aarch64、MIPS等。
编译时常常会出错: undefine reference XXX
,显然是不识别函数,比如 _ZN9fast_gicp7NDTCudaIN3pcl9PointXYZIES2_EC1Ev
,但是这个名称看得不清晰,看不出原来的函数原型。
先执行nm -D libhdl_localization_nodelet.so | grep NDTCuda | grep EC1Ev
,输出1
U _ZN9fast_gicp7NDTCudaIN3pcl9PointXYZIES2_EC1Ev
再执行命令 c++filt _ZN9fast_gicp7NDTCudaIN3pcl9PointXYZIES2_EC1Ev
(去掉前面的 U), 输出函数原型1
fast_gicp::NDTCuda<pcl::PointXYZI, pcl::PointXYZI>::NDTCuda()
c++filt
命令确实太好用了。
ldconfig
有时装完某个库后,需要使用命令sudo ldconfig -v
,否则在程序运行后会出现找不到动态库的问题: error while loading shared libraries: liblog4cpp.so.5: cannot open shared object file: No such file or directory
ldconfig是一个动态链接库管理命令,为了让动态链接库为系统所共享,还需运行动态链接库的管理命令
ldconfig
通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令.主要是在默认搜寻目录(/lib
和/usr/lib
)以及动态库配置文件/etc/ld.so.conf
内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*
),进而创建出动态装入程序(ld.so
)所需的连接和缓存文件.
ldconfig与运行程序时有关,跟编译时一点关系都没有。 不管做了什么动态库的变动后,最好都ldconfig一下
问题 error while loading shared libraries … file too short
这个错误应该是从别处拷贝so文件过来时出现了软链接错误。删除,重新创建这个软连接即可。
比如A,B,C的链接关系: A --> B
, B --> C
。先把C重命名,删掉A,B。重新建立软链接1
2ln -s C B
ln -s B A