Linux 动态库踩坑:明明重新编译了 .so,调用函数返回值却一直不变(libfjrobot.so 版本号异常排查实录)

最近在写机器人 SDK 的 Demo 程序,遇到一个非常经典的动态链接坑:Demo 调用 libfjrobot.so 里的 GetSDKVersion() 获取版本号,无论怎么修改库源码、重新编译,打印出来的版本号始终和预期不一致。

现象

我修改 SDK 源码、执行 make 重新编译生成新的 libfjrobot.so,编译日志看着一切正常,但是运行 Demo 后,GetSDKVersion() 返回的版本号一直是旧值,不会更新。

第一步排查:确认程序到底加载了哪一份 so

Linux 下程序运行时,动态链接器会按照固定的搜索顺序去找 .so 文件,并不是优先加载当前目录或者你刚刚编译出来的库 。 用 ldd 命令查看 Demo 实际依赖的库路径:

复制代码
ldd ./demo

我的输出:

复制代码
libfjrobot.so => /lib/libfjrobot.so

问题直接定位: Demo 加载的是 /lib/libfjrobot.so,是之前拷贝到系统目录的旧版本库;我本地新编译出来的 libfjrobot.so,程序根本没有加载。 哪怕我反复编译本地源码,程序跑的依旧是老库,版本号自然不会变。

原理:Linux 动态链接搜索顺序:LD_LIBRARY_PATH → /etc/ld.so.conf 配置路径 → /lib、/usr/lib 等系统默认库目录。系统目录里同名库优先级很高,很容易抢占加载。

两种修复方案

方案 1:开发调试临时方案(推荐日常调试)

运行前设置 LD_LIBRARY_PATH,优先加载本地编译出来的库,不改动系统文件:

复制代码
# 指定优先搜索本地库路径
export LD_LIBRARY_PATH=./x86-64:$LD_LIBRARY_PATH
# 校验加载路径是否切换成功
ldd ./demo
# 启动demo
./demo

新开终端需要重新执行这条环境变量命令,适合开发调试,不会污染系统。

方案 2:永久替换(我本次使用的方案,虚拟机开发环境适用)

⚠️ 注意:只适合专属开发虚拟机,生产环境不要随意操作 /lib!

  1. 删除系统目录里遗留的旧库

    rm -f /lib/libfjrobot.so

  2. 把刚刚编译完成的新版库复制到系统库目录

    cp ./x86-64/libfjrobot.so /lib/

再次运行 Demo,GetSDKVersion() 返回版本号和源码预期一致,问题解决。

相关推荐
箓维1 小时前
TCP Socket的基础实现
网络·网络协议·tcp/ip
旖旎夜光1 小时前
LCR 170:交易逆序对的总数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法
你看我名字2 小时前
云计算工程师技能树:从 Linux 基础到云平台架构能力
linux·架构·云计算
小向是个Der10 小时前
嵌入式进阶——MCU上电后的动作
c语言·单片机·mcu·学习·链接脚本
dtq042410 小时前
C++小案例 - 日志实战
开发语言·c++
qq_4017004110 小时前
Linux设备树详解
linux·运维·服务器
车软学堂11 小时前
从测试转开发,到底要补什么
网络·人工智能·python·功能测试·单片机·车载系统·自动化
码匠许师傅11 小时前
【C++三方组件】Qt 概览:桌面 C++ 的事实标准与许可证三轨
开发语言·c++·qt
云梦谭11 小时前
让 Linux 主动连接 Windows:配置 Windows 11 SSH 服务端
linux·windows·ssh