linux程序依赖的第三方库相互冲突问题

9 篇文章 0 订阅
7 篇文章 0 订阅

Linux下的软件开发,因为有着众多的开源项目助力,开发难度应该降低很多才是。但是如果用的开源库太多了,偶尔也会遇到2个开源库相互冲突的问题。好比正在干活,有两个好朋友一起过来帮忙,但是活没有干完,这两个好朋友却先起冲突干起来了。人在江湖,朋友多了,似乎朋友之间的矛盾也成了自己的矛盾。-------------------------摘自某某码农开发笔记。

特别是在纯C的软件开发中,如果依赖的2个第三方库,有同名的函数,变量或宏定义,那么麻烦就大了去了。有人说,难道编译不过吗?不是,还真不影响编译。但就是编译时候,编译器无法判定这样的问题是错误,无法强制中断编译,就把问题掩盖下来了。直到运行期间,搞几个随机的bug,让你痛苦地debug。

问题背景

2个依赖的so库文件,如果有着同名的函数,变量或宏,会带来什么灾难呢?
比如A,B这2个库有一个同名的枚举定义, 但是对应的整型数值不一致,在调用过程里,到底真实调用的是哪一个值?随机的,这就是一个炸弹了。

这样的问题,还真让我遇上了, 某项目C依赖开源项目libev库开发的,但是某一天,该项目需要集成另外一个自定义的库D。但是库D又依赖于开源项目libevent。

问题分析

我也是掉入坑里后,通过debug发现,libev和libevent这2个库,居然有很多同名的宏和枚举变量。好家伙,软件一启动,就crash了。用gdb跟踪下,发现居然死在不可能出错的地方,再仔细看,引用libev的某某枚举的赋值,居然不对了,差点颠覆世界观。当然,捉住了鬼,自然就不怕了,软件居然在需要调用libev的这个变量时,错误的引用了libevent的同名宏定义。

自此确认,我掉入坑里了。

出坑填坑

第一个想法是:如何让“ldd 可执行文件” 的列表里,不同时出现2个相互冲突的so文件?
第二个想法是:如何不通过编译依赖关系去调用一个共享库文件里的函数?

有了以上2个想法后,根据经验,自然想到了dlopen的办法。
通过dlopen打开so文件,然后,将so文件里的函数名funcA作为参数,包装出一个函数指针变量d_funcA;最后,在原来需要调用funcA的地方,全部替换换成d_funcA的调用。
示例代码如下:

typedef int (*CONNECT_TO_SVR)(char*, int, int, char*, int);
static CONNECT_TO_SVR d_connect_to_svr = NULL;

void *handle = NULL;
char *error = NULL;

handle = dlopen("libsvrsdk.so", RTLD_LAZY | RTLD_DEEPBIND);
if (!handle) {
    LOG_ERROR("failed to dlopen libsvrsdk.so\n");
    return 1;
}

dlerror();   /* Clear any existing error */
if ((error = dlerror()) != NULL)  {
    LOG_ERROR("failed to dlopen libsvrsdk.so, error info:%s\n", dlerror());
    return 2;
}

d_connect_to_svr = (CONNECT_TO_SVR)dlsym(handle, "connect_to_svr");
if ((error = dlerror()) != NULL)  {
    LOG_ERROR("failed to dlsym connect_to_svr, error info:%s\n", dlerror());
    return 3;
}

同时必须指定so文件加载的路径,

export LD_LIBRARY_PATH=/home/wll/business_serve/build/lib:$LD_LIBRARY_PATH

总结

1. 使用dlopen调用so里的函数,肯定不是正常情况下引用第三方库的好办法
因为这样使用太不方便,关键的是在编译阶段,编译器无法帮助你检查调用的函数是否存在,传入的参数类型是否正确,一切都必须等到runtime的时候才能见分晓。

2. 但是在这里,dlopen可能是唯一的解决办法
并且需要注意,dlopen传入的参数“RTLD_LAZY | RTLD_DEEPBIND”, 这2个参数也是有讲究的。

3.函数dlopen加载so的路径问题
和应用寻找依赖的so库路径类似,只要指定了LD_LIBRARY_PATH环境变量,并将so文件放入LD_LIBRARY_PATH的路径里,就可以确保dlopen能找到该so文件。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Python 中安装第三方库非常简单,可以使用 pip 工具快速安装。 1. 首先打开命令行窗口(Windows 操作系统中可以使用快捷键 Win + R 打开运行窗口,输入 cmd 后回车即可打开命令行窗口)。 2. 在命令行窗口中输入以下命令,安装第三方库: ``` pip install <库名> ``` 例如,安装 requests 库: ``` pip install requests ``` 3. 如果需要安装指定版本的库,可以使用以下命令: ``` pip install <库名>==<版本号> ``` 例如,安装 requests 库的 2.25.1 版本: ``` pip install requests==2.25.1 ``` 4. 如果需要升级已安装的库到最新版本,可以使用以下命令: ``` pip install --upgrade <库名> ``` 例如,升级已安装的 requests 库: ``` pip install --upgrade requests ``` 5. 如果需要卸载已安装的库,可以使用以下命令: ``` pip uninstall <库名> ``` 例如,卸载已安装的 requests 库: ``` pip uninstall requests ``` 以上就是使用 pip 工具在 Python 中安装、升级、卸载第三方库的方法。 ### 回答2: Python作为一种广泛使用的编程语言,拥有丰富的第三方库供开发者使用。下面是关于Python安装第三方库的步骤和方法。 1. 使用pip安装:pip是Python的包管理工具,可以方便地安装和管理第三方库。打开终端或命令提示符,输入以下命令安装相应的库: ``` pip install 库名 ``` 例如:要安装requests库,可以输入`pip install requests`,然后等待安装完成即可。 2. 使用conda安装:conda是一个流行的Python包管理器,特别用于科学计算。如果你已经安装了Anaconda,那么conda命令在其中包含了。打开终端或命令提示符,输入以下命令安装相应的库: ``` conda install 库名 ``` 例如:要安装numpy库,可以输入`conda install numpy`,然后等待安装完成即可。 3. 下载源代码安装:有些第三方库可能没有上传到Python的包管理工具中,这时候可以从官方网站或开源代码托管平台上下载源代码进行手动安装。通常,下载源代码后,解压缩文件,打开终端或命令提示符,进入解压缩后的目录,然后执行以下命令: ``` python setup.py install ``` 这将会自动安装该第三方库。 4. 使用IDE集成的包管理器安装:一些Python集成开发环境(IDE)提供了自己的包管理器,例如PyCharm的Project Interpreter。在IDE中打开该功能,并搜索要安装的库,使用IDE提供的安装按钮或命令即可安装。 无论你选择哪种安装方式,都需要保证你的Python环境已经正确配置,并且能够连接到互联网。如果你碰到安装问题,可以参考相应的文档或搜索网络上的解决方案。另外,建议使用虚拟环境来隔离不同项目使用的第三方库,以免发生版本冲突或其他不兼容问题。 ### 回答3: 安装第三方库是Python开发中的常见操作,以下是Python安装第三方库的步骤: 1. 确定第三方库的名称:在开始安装之前,需要确定要安装的第三方库的名称。可以通过搜索引擎或官方文档来获取所需库的名称。 2. 打开命令行工具:在Windows系统中,可以打开命令提示符或PowerShell;在Mac或Linux系统中,可以打开终端。 3. 使用pip命令安装:pip是Python的包管理工具,大多数第三方库都可以通过pip来安装。在命令行中输入以下命令: ``` pip install 第三方库名称 ``` 其中,第三方库名称是要安装的库的名称。 4. 等待安装完成:pip命令会自动从Python包索引中下载并安装所需的库文件。等待安装完成。 5. 验证安装结果:安装完成后,可以通过导入库并执行一些简单的操作来验证是否成功安装。例如,在Python交互界面中输入以下代码: ``` import 第三方库名称 print(第三方库名称.__version__) ``` 其中,第三方库名称是要验证的库的名称。如果输出了库的版本号,则说明安装成功。 需要注意的是,有些第三方库可能需要提前安装一些依赖项,例如其他的库或者系统工具。这些依赖项通常在库的官方文档中有详细说明,需按照说明进行安装,然后再安装所需的库。 总之,Python安装第三方库一般通过pip命令完成,安装步骤包括确定库名称、打开命令行工具、使用pip命令安装、等待安装完成、验证安装结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值