C++动态链接问题的几种解决方法
Posted 走过_冬天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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在背后干了什么根本不知道,也无法控制。当然如果没遇到这些坑我也不会去找这么多的方法。
以上是关于C++动态链接问题的几种解决方法的主要内容,如果未能解决你的问题,请参考以下文章