Linux 下 C++ 编程过程中开发环境中踩过的坑

Linux 下 C++ 编程过程中开发环境中踩过的坑

[TOC]

本文记录一些 Linux 下 C++ 编程过程中典型的配置开发环境中踩过的坑, 以期待举一反三. 并持续整理更新.

缺失库

报错输出: 一般比较简单, 关键词是 not found.

问题解决思路:

  1. 首先查找系统中是不是在别的位置中存在该库. 暴力手段如下:

    1
    sudo find / -name LIB_NAME

    如果报错信息中不存在缺失库的名字, 可以用 ldd 命令查找无法运行的库的依赖库项.

    如果查到了创建其软链接到调用库的目录下, 观察是否可以使用.

  2. 系统中不存在此库, 或者版本不匹配. 此时最关键的问题来了, 很多库名不是直接对应其源码包/二进制文件名的, 需要耐心搜索. 例如我在 ros2 run rviz2 rviz2 时报错缺失 libassimp.so.5, 搜到其对应的 apt 库名字为 libassimp-dev. 这个算是对照比较工整的名字了.

    • 网上下载二进制文件
    • 下载源码包, 编译后安装到所需位置.
  3. 查不到, 下载不了, 还是不匹配: 找同事拷贝吧.

库匹配错误

虽然找到了库, 但是应用发现库不匹配. 通过实例介绍.

ROS 中不匹配库

例如在 ROS 中不匹配库的报错示例:

1
symbol lookup error LIB_NAME.so: undefined symbol

还是 ros2 run rviz2 rviz2 报错 symbol lookup error librcl_logging_spdlog.so: undefined symbol, 这个库应该是 ROS 生态圈里的专用库, 因此用搜索引擎搜索都得不到什么结果. 因为报错信息里有库名, 先直接 find 搜索. 发现果然有 2 处目录下存在相同的库.

1
2
/opt/ros/galatic/lib/librcl_logging_spdlog.so #报错的是此库
/home/USER/ros/galatic/lib/librcl_logging_spdlog.so #新搜出来的库

然后用 md5sum 检查两个库的 checksum 值, 发现果然不一样, 得出结论: 另一个位置的库可能是可用的. 备份替换:

1
2
sudo mv /opt/ros/galatic/lib/librcl_logging_spdlog.so /opt/ros/galatic/lib/librcl_logging_spdlog.so_bk
sudo ln -s /home/USER/ros/galatic/lib/librcl_logging_spdlog.so /opt/ros/galatic/lib/librcl_logging_spdlog.so

再运行一遍发现报错消除了.

问题的关键是, 不知道什么原因这个库在安装后(/opt/ros/galatic/lib/)与 ROS2 官方二进制压缩包(/home/USER/ros/galatic/lib/)里的库相比发生了变化.

除了软链接, 可以将 /home/USER/ros/galatic/lib/opt/ros/galatic/lib/ 的位置在 LD_LIBRARY_PATH 环境变量里调换, 调整优先使用顺序.

上面调整顺序的方法不太优雅, 原因如下:

  1. 修改环境变量打字很麻烦.
  2. 最关键的是, 整个目录下所有的库的优先级都被调整了, 如何只针对一个库的优先级进行调整呢?

动态库加载顺序

Linux 下动态库的一般加载顺序如下:

  1. 编译目标代码时使用 -Wl, -rpath 指定的动态库搜索路径. 这个具有最高优先级.
  2. 环境变量 LD_PRELOAD 指定的目录. 无论程序是否依赖于它们, LD_PRELOAD 里面指定的共享库或目标文件都会被装载. 全局符号就会覆盖后面加载的同名全局符号, 这使得我们可以很方便地做到改写标准 C 库中的某个或某几个函数而不影响其他函数, 对于程序的调试或测试非常有用.
  3. 环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径.
  4. 配置文件 /etc/ld.so.conf 中指定的动态库搜索路径. 配置后要运行 ldconfig 命令才能生效.
  5. 默认的动态库搜索路径 /lib.
  6. 默认的动态库搜索路径 /usr/lib.

根据我们对优雅性的要求, 我们可以发现 LD_LIBRARY_PATH 指定最符合要求, 编辑/删除都比较方便, 只影响一个库而不是一堆库:

1
export LD_LIBRARY_PATH=/home/USER/ros/galatic/lib/librcl_logging_spdlog.so:$LD_LIBRARY_PATH

如果需要么此启动终端都加入, 将上面命令放入 ~/.bashrc 中.

这种方法虽然没有软链接这么直接, 但是在保证不同版本的库共存的前提下还是很有用的思路.

环境变量设置

还是 ros2 run rviz2 rviz2 报错…

1
Qt: Session Management Error

解除现有的 SESSION_MANAGER 环境变量设置:

1
export -n SESSION_MANAGER

并放入 ~/.bashrc 中不用每次配置.

此案例参考链接.

参考链接:

https://bbs.huaweicloud.com/blogs/156745

Linux 下 C++ 编程过程中开发环境中踩过的坑

https://www.chuxin911.com/linux_cpp_development_environment_config_20220519/

作者

cx

发布于

2022-05-19

更新于

2022-07-16

许可协议