C++动态链接问题的几种解决方法

"undefined reference to function(xxx)"是一个非常常见问题,每个C++程序员应该都不会感到陌生。与之相伴的通常还有一个“No such file xxx.h”,一般是头文件找不到的问题。这种问题相对简单,因为头文件的查找发生在编译期,如果头文件没找到,当然链接的问题可能还没机会暴露。

武林秘籍也分招式和心法,招式更像是““undefined reference to问题汇总”。当遇到类似问题的时候,总是对照汇总中的招式,一个个比对解决。招式和心法都很重要,都能解决问题,但招式太多了就容易忘记,所以记性不好的人应该学好心法。而今天要说的更像是心法。

程序链接分两种,一种是静态链接, 一种是动态链接,静态链接发生在编译期,动态链接发生成运行期,今天记录的是编译通过后在运行时遇到的“undefined reference to”问题的解决方法。

方法一:查看文件链接了哪些文件和链接文件的目录。

zx-pc:$ ldd xxx_driver_test 
	linux-vdso.so.1 =>  (0x00007ffff81ce000)
	libgui.so => /home/zx/Projects/perception_proj/build/release/example/gui/libgui.so (0x00007fc54680e000)
	libopencv_core.so.3.3 => /usr/local/lib/libopencv_core.so.3.3 (0x00007fc54549b000)
	libvtkCommonCore-7.1.so.1 => /usr/local/lib/libvtkCommonCore-7.1.so.1 (0x00007fc544c8d000)
	libglog.so.0 => /usr/local/lib/libglog.so.0 (0x00007fc544a5c000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc54483f000)
	libboost_system.so.1.58.0 => /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0 (0x00007fc54463b000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc544258000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc544040000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc543c76000)

方法二:通过进程监视器查看
ubuntu搜索打开System Monitor,鼠标移动到进程上就会显示程序运行的命令,可以查看命令中的环境变量目录是否正确。
在这里插入图片描述
对应的也可以在/proc/PID/cmdline中看到程序执行命令。

cat /proc/<PID>/cmdline

在这里插入图片描述

如果运行的时候环境发生变化,比如安装了多个版本的库,查看运行用的是哪个版本,就可以看这里

方法三:使用lsof命令

lsof -p <PID>
zx-pc:~$ lsof -p 21059
COMMAND     PID USER   FD      TYPE  DEVICE SIZE/OFF    NODE NAME
card_dete 21059   zx  cwd       DIR   259,3     4096 8521404 /home/zx/.ros
card_dete 21059   zx  rtd       DIR   259,2     4096       2 /
card_dete 21059   zx  mem       REG   259,2    43456 3298719 /usr/lib/x86_64-linux-gnu/libOpenCL.so.1.0.0
card_dete 21059   zx  mem       REG   259,2    34624 3288025 /usr/lib/x86_64-linux-gnu/libogg.so.0.8.2
card_dete 21059   zx  mem       REG   259,2   104688 3288290 /usr/lib/x86_64-linux-gnu/libtheoradec.so.1.1.4
card_dete 21059   zx  mem       REG   259,2   256360 3288292 /usr/lib/x86_64-linux-gnu/libtheoraenc.so.1.1.2
card_dete 21059   zx  mem       REG   259,2   278352 5128509 /opt/ros/kinetic/lib/libtheora_image_transport.so
card_dete 21059   zx  mem       REG   259,2   142232 5127965 /opt/ros/kinetic/lib/libimage_transport_plugins.so
card_dete 21059   zx  mem       REG   259,2   269888 5128307 /opt/ros/kinetic/lib/libcompressed_image_transport.so
card_dete 21059   zx  mem       REG   259,2    22816 5127999 /opt/ros/kinetic/lib/libdynamic_reconfigure_config_init_mutex.so
card_dete 21059   zx  mem       REG   259,2   240944 5128306 /opt/ros/kinetic/lib/libcompressed_depth_image_transport.so
card_dete 21059   zx  mem       REG   259,2    47648  792165 /lib/x86_64-linux-gnu/libnss_nis-2.23.so
card_dete 21059   zx  mem       REG   259,2    93128  786516 /lib/x86_64-linux-gnu/libnsl-2.23.so
card_dete 21059   zx  mem       REG   259,2    35688  786528 /lib/x86_64-linux-gnu/libnss_compat-2.23.so
card_dete 21059   zx  mem       REG   259,2    47600  786526 /lib/x86_64-linux-gnu/libnss_files-2.23.so

三种方法都可以找目录,有的情况可能是编译时链接的文件与运行时链接的文件不是同一个文件,这个时候ldd命令查看的方法可能找不到问题。这种情况使用lsof命令更好,先运行程序,再查找程序的PID。再看运行真正链接的目录。

ros是一个神奇的东西,遇到过很多次奇怪的问题,比方说在ros工程下CMakeList.txt设置执行文件输出目录

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../install/bin)

编译后没有看到输出的执行文件。如果通过install的方式

install(TARGETS ${PROJECT_NAME}_node
    RUNTIME DESTINATION ${EXECUTABLE_OUTPUT_PATH}
    )

可以在对应目录输出执行文件,但ldd命令查看执行文件的链接有的为not found。
更神奇的有使用roslaunch启动程序链接的文件可能与编译时链接的不是同一个文件。这个时候你根本不知道程序链接的是哪个文件,所在ldd命令已经不从下手了。catkin_make在背后干了什么根本不知道,也无法控制。当然如果没遇到这些坑我也不会去找这么多的方法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值