linux 编译查看链接库详情,Linux环境下的编译,链接与库的使用

链接参数控制

链接器中提供了-dn -dy 参数来控制使用的是动态库还是静态库,-dn表示后面使用的是静态库,-dy表示使用的是动态库

例:

g++ -Lpath -Wl,-dn -lx -Wl,-dy -lpthread 这样如果在path路径下有libx.so和libx.a这个时候只会用到 libx.a.

注意在最后的地方如果没有-Wl,-dy 让后面的库都使用动态库,可能会报出 “cannot find -lgcc_s” 的错误,这是由于glibc的.a库和.so库名字不同,–static会自动处理,但是 -Wl,-dy却不会去识别这个问题.

小提示:

如果使用–static, 由于-dy的使用导致后面的库都是共享库(dy强制屏蔽了静态库),这个时候编译出来的程序和只有动态库的情况下强制使用–static编译一样都会报错

运行报错 ”undefined reference to `xxx()’ ” 对 于动态链接库,实际的符号定位是在运行期进行的.在编译.so的时候,如果没有把它需要的库和他一起进行联编,比如libx.so 需要使用uldict, 但是忘记在编译libx.so的时候加上-luldict的话,在编译libx.so的时候不会报错,因为这个时候libx.so被认为是一个库,它里面 存在一些不知道具体实现的符号是合法的,是可以在运行期指定或者编译另外的二进制程序的时候指定.

如果是采用 g++ -Lpath -lx 的方式进行编译,链接器会发现所需要的uldict的符号表找不到从而报错,但是如果是程序采用dlopen的方式载入,由于是运行期,这个程序在这个地 方就直接运行报错了. 另外还有一种情况就是一个对外的接口在动态库中已经声明定义了,但是忘记实现了,这个时候也会产生类似的错误.

如果在运行期报出这样的错误,就要注意是否是由于某些库没有链接进来或者某些接口没有实现的原因产生

日志库问题 其实不只是日志库存在这样的问题,其他需要同时被多个动态库以及主程序同时使用的函数其实都存在这样的问题.这里主要以日志库的问题为例来说明这些问题.

有 一个程序,它通过dlopen的方式调用了一个.so文件. 在这个主程序中和.so中都使用了日志库,主程序中使用ul_openlog打开了日志, 在.so中没有用ul_openlog打开日志.这个时候发现,主程序中的日志正常输出,但.so中的日志却直接输出到了标准出错.

这个问 题的原因在前面的其实已经提到了,在默认情况下主程序中使用的接口对于.so是不可见的,.so所在的代码空间与主程序的代码空间是隔离的,这个时 候.so调用的ul_writelog其实是没有经过ul_openlog的那块代码空间,由于ul_log库使用了一些static变量(如果是带 comlog的ul_openlog那还有全局符号),只有在ul_writelog, ul_openlog都是在同一块空间上的时候才会起作用.

这个问题的一个最简单的解决方案是

在主程序的链接的时候加入-rdynamic,仍然链接libullib.a库 编译动态链接库时,不加链接libullib.a库 其实动态库这里是否链了libullib.a已经不重要了,在有-rdynamic的情况下,.so中如果有与主程序同名的函数那么会优先调用主程序中的函数, 动态库不链接libullib.a倒是可以省点空间

但是这种方式在某些情况还是不能完全解决问题

假 设有A.so, B.so,主程序main, 在A.so中调用了ul_openlog, B.so中没有调用ul_openlog, 但调用了ul_writelog. 在主程序中没有调用ul_log中的任何接口和使用任何变量.这种情况下即时使用了-rdynamic还是会导致在 A.so中正常输出日志,但在B.so中却把日志输出到标准出错.

这个问题的主要原因在于,gcc在链接的时候是以.o为单位的,如果一 个.o中的符号没有被外部所使用,那么在链接的时候就不会把这个.o中的符号给链接进行.so或者二进制程序中.在上面的问题中主程序里面没有调用到日志 库中的任何符号,所以在链接的时候就不会把ullib中的ul_openglog和ul_writelog给链接进行主程序中,这个时候即使有 -rdynamic也是做不到让.so中的动态链接库都使用.

这个问题一般有下面几种方案:

载入A.so的时候使用RTLD_GLOBAL参数,把A.so中的所有的符号都变成对外可见,这样A.so和B.so的ul_writelog都在一块代码空间中了 编译主程序的时候链接ullib的地方由-lullib改为 -Wl,–whole-archive -lullib -Wl,–no-whole-archive, 同时加上-rdynamic. -Wl, –whole-archive是链接参数,它表示把ullib的中所有的符号都链接进主程序中,而不管主程序是否调用了ullib中的符 号.-Wl,–no-whole-archive表示后面的链接取消–whole-archive的行为,毕竟其他的库没有必要采用这种方式全部链接 进来. 在主程序中随便调一下ul_log中的符号,比如可以先随便ul_openlog一下,然后ul_closelog, 后面再进行动态库调用. 把libullib.a用 ar x 命令还原成多个.o文件,采用直接链接的方式使用ul_log.o. 上 面的几个问题的产生主要还在于静态链接和动态链接混用,而两种链接方式又存在不一样的地方.事实上如果我们把ullib库 采用动态链接库的方式编译成 libullib.so, 采用前面的方式在编译期链接libullib.so,并且设置LD_LIBRARY_PATH, 上面的2个问题都不会存在. 编译期使用的.so,是全局可见的,不需要-rdynamic也可以被dlopen的动态库所用到,由于是动态链接库,所以 包含了所有的符号,不会像静态库那样只包含了所用到的.o中的符号. 事实上这也是多数第三方程序的解决方案

主程序中使用-rdynamic会对后续的升级造成一些麻烦:

加上-rdynamic后,像日志库这样的基础如果需要升级, 那么就必须要升级主程序, 使用的.so无论如何升级所用到的ul_writelog都是主程序中的. 主程序中除了日志库,还会有其他库或者函数的存在, 这些函数如果不是static的就有可能与 dlopen打开的so中的函数混到一起,造成困惑 如果.so中需要打印它自己的日志, 那样需要comlog本身功能的支持才可以实现,而不能简单的使用ul_writelog来实现 但是如果主程序中没有使用-rdynamic,那么又有下面的这些麻烦 dlopen打开的动态库日志是打印自己的, 不能和主程序统一在一起. 如果.so的程序和主程序open的是同一个日志,这相当于多进程打日志, 那必须要comlog的支持,ullog本身不支持多进程打同一个日志. 如果主程序中用dlopen+RTLD_GLOBAL的打开了某个.so 日志的问题就可能影响到其他的.so中的调用. 同时对于一些老程序, 升级前后-rdynamic 可能也会产生影响,比如两次ul_openlog 这里对于类似日志库这种需要全局状态变量支持的库提出另外方案

编译一个专门的.so, 这个.so中包括了其它.so中所需要的所有和全局量相关的接口 2. 主程序不使用-rdynamic编译, 但打开上面的.so的时候,采用RTLD_GLOBAL方式,并且是第一个打开 3. 除了打开第一个 .so, 其它的.so都不使用RTLD_GLOBAL方式, 并且在编译的时候都不把和第一.so相关的库联编 4. 第一个.so的升级需要保证没有其它.so在运行才可以dlclose, 重新dlopen

这个问题首先需要明确需求, 到底是希望每个.so打自己独立的日志,还是和主线程统一

这 里要注意另外一个问题就是目前的ullib 日志库情况比老的ullog要复杂, 在comlog中引入一些extern 出来的全局变量 在采用dlopen的时候,对于一般符号,一般都是主程序和动态库在两块空间中, 但是对于使用extern出来的变量主程序和动态库都是在一块空间中(注:由于32位下不用-fPIC也可以编译so, 在没有-fPIC的情况也是分开的, 但是由于64位一定要-fPIC所以一定会出现同一块空间的问题), 对于这个问题的解决方案是在动态库链接的时候加上 -Wl,-Bsymbolic 参数将动态库的空间和主程序的空间强行分开。

上面有提到 编译动态链接库时,不加链接libullib.a库,但主程序使用-rdynamic, 这里主要是为了避免使用到了不同的ullib导致调用了一些不同的内部符号,导致出现另外的麻烦

对于动态库中的日志建议采用下面的几个方案:

动态库完全打自己的,日志,编译二进制程序不要用-rdynamic, 动态库链接的编译加上 -Wl,-Bsymbolic 参数 , 链接ullib, 在动态库中自己open,自己控制等级 1. 动态库不链接ullib, 编译二进制程序用-rdynamic , 这样可以正确的使用主程序中的日志库,也规避了版本不一致带来的问题, 但是这样失去了对于动态库日志的控制, 而且存在升级的不便, 日志的升级是由主程序控制的。

小提示:

有关动态库使用的例子还可以参考 SoTips 在运行期可以通过设置环境变量LD_DEBUG查看每个符号具体链接到了什么地方,每个符号具体的查找过程和绑定过程.可以这样使用 export LD_DEBUG=help 随便运行一个程序就可以看到对于LD_DEBUG的使用说明

export LD_DEBUG=files./main 可以看到整个装载过程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458942.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在C++中用虚函数的作用是什么? 为什么要用到虚函数?

***************************************************更多精彩,欢迎进入:http://shop115376623.taobao.com***************************************************虚函数联系到多态,多态联系到继承。所以本文中都是在继承层次上做文章。没了继…

mysql 主主互备实现

今天星期天,么事就写个MYSQL的主主架构的博客,原理如下图,不是我画的网上找的。主机作用操作系统mysql版本对应IPvip数据库mysqlA(主)centos6.4mysql 5.5.48192.168.48.129192.168.48.126mysqlB(备)centos6.4mysql 5.5.48192.168.48.132一&am…

Linux Deepin 版本大全,Deepin下载-Deepin linuxv20.0 官方版下载-6188手游网

Deepin linux安装准备一:为 Deepin 留出硬盘空间以便安装。1.打开磁盘管理(Windows 徽标上右键单击,选择磁盘管理)。2.选中一个分区(空闲空间大于 30G),我选择的是 C 盘,因为是固态硬盘所以安装启动会快很多。磁盘 1 的 200G 分区…

动手实践 Linux VLAN - 每天5分钟玩转 OpenStack(13)

本节我们来看如何在实验环境中实施和配置如下 VLAN 网络 配置 VLAN 编辑 /etc/network/interfaces,配置 eth0.10、brvlan10、eth0.20 和 brvlan20。 下面用 vmdiff 展示了对 /etc/network/interfaces 的修改 重启宿主机,ifconfig 各个网络接口 用 brct…

Socket的3次握手链接与4次断开握手

*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com *************************************************** 连接握手: 1.客户端发送建立连接请求 (发送请求)2.…

Linux桌面需要强制访问控制,RHCSA 系列(十三): 在 RHEL 7 中使用 SELinux 进行强制访问控制...

RHCSA 认证:SELinux 精要和控制文件系统的访问尽管作为第一级别的权限和访问控制机制是必要的,但它们同样有一些局限,而这些局限则可以由安全增强 Linux(Security Enhanced Linux,简称为 SELinux)来处理。这些局限的一种情形是&am…

使用canvas实现擦玻璃效果

体验效果:http://hovertree.com/texiao/html5/25/效果图&#xff1a;代码如下&#xff1a; <!DOCTYPE html> <html> <head lang"zh"> <meta name"viewport" content"initial-scale1.0, maximum-scale1.0, user-scalableno, widt…

如何计算时间复杂度

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 求解算法的时间复杂度的具体步骤是&#xff1a; ⑴ 找出算法中的基本语句&#xff1b;…

linux显示系统信息软件下载,linux查看系统信息软件安装信息命令学习笔记

查看LINUX安装版本[rootlocalhost etc]# unameLinux[rootlocalhost etc]# uname -aLinux localhost.localdomain 2.6.32-279.11.1.el6.i686 #1 SMP Tue Oct 16 14:40:53 UTC 2012 i686 i686 i386 GNU/Linux[rootlocalhost etc]# cat /proc/versionLinux version 2.6.32-279.11.…

Bzoj 2662: [BeiJing wc2012]冻结 dijkstra,堆,分层图,最短路

2662: [BeiJing wc2012]冻结 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 647 Solved: 348[Submit][Status][Discuss]Description “我要成为魔法少女&#xff01;” “那么&#xff0c;以灵魂为代价&#xff0c;你希望得到什么&#xff1f;” “我要将有关魔法和奇…

[转]opencv学习资料

转自&#xff1a;http://blog.csdn.net/poem_qianmo/article/details/20537737 1&#xff1a;Mat imread(const string& filename, intflags1 ); eg: Mat image0imread("dota.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);//载入最真实的图像 ge1i…

linux servlet 乱码问题,Servlet一次乱码排查后的总结

由来在写一个小小的表单提交功能的时候&#xff0c;出现了乱码&#xff0c;很奇怪request上来的参数全部是乱码&#xff0c;而从数据库查询出来的中文显示到页面正常&#xff0c;锁定肯定是request对象那里出了问题。后来经过排查&#xff0c;发现是我封装的框架中出了问题&…

C/C++回调函数

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 对于很多初学者来说&#xff0c;往往觉得回调函数很神秘&#xff0c;很想知道回调函数…

Linux 命令[2]:mkdir

make directories mkdir -p [目录名] -p 递归创建 [rootlocalhost ~]# mkdir -p test [rootlocalhost ~]# ls anaconda-ks.cfg install.log install.log.syslog test 当然只创建一个目录 -p 是可以省略的 注&#xff1a;如果创建多级目录没有 -p 会报错 如&#xff1a; [roo…

jQuery动态设置样式List item

前段时间&#xff0c;Insus.NET有修改一个功能《激活当前视图菜单高亮呈现》http://www.cnblogs.com/insus/p/5287093.html 今天Insus.NET想改用另外一个方法来实现&#xff0c;使用jQuery。在ASP.NET MVC 环境实现&#xff1a; 代码&#xff1a; <ul><li><a hr…

linux telnet 权限,允许telnet 通过root用户进行访问

允许telnet 通过root用户进行访问RHEL6:[rootclovem ~]# yum install telnet-server -y //安装telnet服务端[rootclovem ~]# cat /etc/xinetd.d/telnet //开启telnet的托管服务# default: on# description: The telnet server serves telnet sessions; it uses \#unencrypt…

TOUGHRADIUS 项目介绍

2019独角兽企业重金招聘Python工程师标准>>> TOUGHRADIUS 项目介绍 ToughRADIUS是一个开源的Radius服务软件&#xff0c;采用于 Apache License 2.0 许可协议发布&#xff0c;从创立之日起&#xff0c;他的宗旨就是服务于中小微ISP&#xff0c;让运营变得更简单。 T…

转:Jmeter 用户思考时间(User think time),定时器,和代理服务器(proxy server)...

在负载测试中需要考虑的的一个重要要素是思考时间&#xff08;think time&#xff09;&#xff0c; 也就是在两次成功的访问请求之间的暂停时间。 有多种情形挥发导致延迟的发生&#xff1a; 用户需要时间阅读文字内容&#xff0c;或者填表&#xff0c;或者查找正确的链接等。未…

linux sql语句传参数,Linux/Unixshell参数传递到SQL脚本

在数据库运维的过程中&#xff0c;Shell 脚本在很大程度上为运维提供了极大的便利性。而shell 脚本参数作为变量传递给SQL以及SQL脚本也是DB在数据库运维的过程中&#xff0c;Shell 脚本在很大程度上为运维提供了极大的便利性。而shell 脚本参数作为变量传递给SQL以及SQL脚本也…

Myeclipse5.5获取注册码

2019独角兽企业重金招聘Python工程师标准>>> import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class MyEclipseGen {private static final String LL "Decompiling this copyrighted software is a vi…