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++动态链接问题的几种解决方法的主要内容,如果未能解决你的问题,请参考以下文章

点击表头排序的几种方法 & 动态表格

java导出word的几种方式

linux下把动态链接库加入环境变量的几种方式

c++调用webservice接口的几种方法以及实例

c++调用webservice接口的几种方法以及实例

C++中标志位的几种实现方法