首页 > 系统相关 >Linux 动态库符号冲突

Linux 动态库符号冲突

时间:2023-09-20 11:55:18浏览次数:43  
标签:符号 编译 so 冲突 库中 Linux 动态 链接

问题起源

在Linux下编译动态库的时候,所有的符号默认都是导出的,也就是动态库中的函数名,类名等,在外部都是可见的。

当程序引用多个动态库时,由于各个动态库可能属于不同的团队来开发,不同团队使用相同的第三方库的可能性也是有的(例如openssl,libcurl,cjson等),
不同的团队使用的第三方库的版本大概率都是不同的。在编译期间可能不会产生编译错误,但是在运行时可能会导致符号冲突,
引发的现象是调用相同的函数本地测试的结果和运行时的结果不同。

通过修改链接顺序解决问题

既然是不同版本的库相互影响,假设高版本的库能向下兼容,是否可以修改链接顺序,将高版本的库放在前面,低版本的库放在后面,这样就会先加载高版本的库,问题也可以解决
例如libtest1.so,libtest2.so都有openssl库,但是libtest2.so库中openssl版本比较高,那么可以通过修改链接顺序解决问题

LDFLAGS += -Wl,-rpath .  -L . -ltest2 -ltest1

修改链接顺序对于能向下兼容的第三方库是可以解决问题,但是某些第三方库也是不向下兼容的,例如CJSON

通过链接过程中指定优先使用本动态库中的符号

一般而言,单个动态库中并不会出现符号冲突,动态库内部符号冲突一般在编译过程中就会暴露出来,因此当上层程序调用动态库时,
我们可以设置上层程序优先使用本动态库中的符号,而不是全局符号。这样即使其他动态库导出的符号和自己动态库中的符号同名,冲突也不会发生,
运行自己动态库程序的时候会使用自己本动态库中的函数和类。

LDFLAGS += -Wl,-Bsymbolic

注意:这边编译选项必须在被链接的动态库的编译过程中添加,而不是在上层程序链接第三方库的时候添加,例如test引用liba.so,那么这边编译选项需要在编译liba.so过程中添加

通过隐藏符号表解决问题

既然是符号冲突导致的异常,那么可以把库符号信息进行修改,把库内部调用的符号限定为只能内部调用,外部调用的符号限定为可公共调用。一般方法是在函数前增加 __attribute__ 前缀来控制。
在编译过程中加入-fvisibility=hidden选项,因此符号的可见性。对于想要对外暴露的函数通过函数前增加__attribute__((visibility("default")))来指定输出。

gcc  -g -O0 -Wall -fPIC -fvisibility=hidden   -c test.c -o test.o

附件

查看动态库中的符号表

nm libxxx.so |grep [函数名]

备注: t表示符号是本地符号,T表示符号是全局符号

 

标签:符号,编译,so,冲突,库中,Linux,动态,链接
From: https://www.cnblogs.com/zhanggaofeng/p/17716977.html

相关文章

  • linux关闭终端,后台程序不退出
    你要退出终端会话时,要是存在被停止的进程,会出现警告信息。但如果使用了后台进程,只有某些终端仿真器会在你退出终端会话前提醒你还有后台作业在运行。 如果希望运行在后台模式的脚本在登出控制台后能够继续运行,我再一篇文章中看到,有方法可以实现。有时你会想在终端......
  • (笔记)Linux修改、查看日期和时间的方法
      1、查看时间、日期#dateFriJan1114:04:10CST2019 2、修改时间语法:date-s"时:分:秒"#date-s"17:20:30" 3、修改日期、时间语法:date-s"年-月-日时:分:秒"#date-s"2019-01-1114:21:30"注意:设置时间需要使用双引号括起来,否则会报错。 ......
  • Linux 下安装安装rz/sz命令
    http://www.ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz  下载lrzsz安装包tarzxvflrzsz-0.12.20.tar.gz&&cdlrzsz-0.12.20#解压并切换到lrzsz-0.12.20目录下面yum -yinstall gcc cc./configuremakemakeinstall上面安装过程默认把lsz和lrz安装到了/usr/loc......
  • 22_Linux常用指令
    Linux常用指令终端Ctrl+Alt+T终端多开Ctrl+Shift+T终端切换Alt+numIsIs-IIs-apwdnautilus.Mkdircatcdcd-GeditCpRmFindGrepChmodchmod777*.c给最高权限AdbshellAdbpushAdbpullCode......
  • 25_linux c 多进程
    linuxc多进程什么时候用进程&线程?1、需要频繁创建销毁的优先使用线程;因为对进程来说创建和销毁一个进程代价是很大的。2、线程的切换速度快,所以在需要大量计算,切换频繁时用线程,还有耗时的操作使用线程可提高应用程序的响应。3、多进程可以使用在多机分布式系统,需要扩展......
  • 24_linux c多线程
    linuxc多线程shell脚本创建mkdirEMprjcdEMprj/code.在vscode中新建CMakeLists.txt文件,编写内容:cmake_minimum_required(VERSION2.8)project(demo)add_executable(mainmain.c)新建main.c文件,编写内容:#include<stdio.h>intmain(intargc,charcon......
  • 23_Linux工程搭建
    Linux工程搭建cmake1安装cmake,sudoaptinstallcmake,并编写Cmakelists.txt。2执行命令"cmakePATH"或者"ccmakePATH"生成Makefile(PATH是CMakelists.txt所在的目录)。3使用make命令进行编译。cmake语法#确定cmake最低版本cmake_minimum_required(VERSION2.8)#......
  • 27_linux 网络编程
    linux网络编程HTTP协议对应于应用层,Socket则是对ICP/IP协议的封装和应用Socket的出现只是使得程序员更方便地使用ICP/IP协议栈而已,是对ICP/IP协议的抽象,从而形成了我们知道的一些最基本的函数接口,比如create、listen、connect、accept、send、read和write等。......
  • 26_linux 文件编程
    linux文件编程#include<stdio.h>#include<string.h>#include<fcntl.h>intmain(intargc,charconst*argv[]){intfd,len;char*buf="HelloWorld\n",Out[32];fd=open("a.txt",O_CREAT|O_TRUNC|O_RDWR,0600......
  • linux 中 trimmomatic软件的安装及使用
     001、下载官网:http://www.usadellab.org/cms/?page=trimmomatic 下载0.39版本: 002、上传至linux中,然后解压[root@pc1software]#ls##列出安装包Trimmomatic-0.39.zip[root@pc1software]#unzipTrimmomatic-0.39.zip##解压Archive:......