ldd, nm, c++filt, ldconfig命令

ldd

命令的作用是打印共享库的依赖关系

  1. ldd不是一个可执行程序,而只是一个shell脚本。ldd能够显示可执行模块的 dependency,其原理是通过设置一系列的环境变量,如下:LD_TRACE_LOADED_OBJECTS、LD_WARN、LD_BIND_NOW、LD_LIBRARY_VERSION、 LD_VERBOSE等。

  2. 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
2
/usr/bin/ld: skipping incompatible /home/user/lib/libtinyalsa.so when searching for -ltinyalsa
/usr/bin/ld: cannot find -ltinyalsa: No such file or directory

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
2
ln -s C B
ln -s B A