开发过程中,对于动态库的疑问和思考

开发过程中,对于动态库的疑问和思考

前言:先简述一下开发时的情况。由于工程代码编译是在 Linux 上,可执行文件是在板子(ARM)上去运行。但是我们需要用到hiredis这个库,我发现无论是 Linux 上还是嵌入式系统上,都需要用到 libhiredis.so 这个动态库,而工程代码是已经包含了 hiredis 的全部头文件了,就相当于是已经具备了对 hiredis 这个库调用一些函数或结构体时,已经是有声明的了。

所以我就产生一个疑问:在编译可执行文件时,为什么 Linux 上也需要包含这个动态库才可以成功编译?动态库不是在程序运行起来后才进行链接的吗,不是板子上包含了这个动态库就好了吗?

带着这个疑问,我就去了解了一下。

结论:Linux 上和板子上都需要该动态库。首先,板子上需要就已经毋庸置疑了,因为动态库会在程序执行时进行动态加载并链接。但 Linux 上是因为在编译时,加了链接选项 -lhiredis,有了这个选项,链接器就需要去找到动态库的位置和名称,以便能够正确链接和加载动态库,一旦找到动态库,链接器就会把动态库的符号表信息记录在可执行文件中,然后再解析程序中对动态库的符号引用,以便能够正确地将动态库中的函数调用链接到程序中。如果程序中存在未定义的符号引用,或者说工程代码中没有包含该动态库,链接器就无法解析这些符号,会报链接错误。因此,在编译和链接命令中需要包含对动态库的引用,以告知链接器需要链接哪些函数或符号。


还有再说一下,我上面为什么会提到工程代码中已经包含了 hiredis 的全部头文件呢?这和动态库有什么关系呢?

一开始我是想着,有了头文件,不就已经有了我在代码中需要用到的关于 hiredis 的数据结构和函数定义了吗,在编译成可执行文件时,编译器不就可以找到对应的数据结构和函数定义了吗,就不会导致未定义的情况,就不需要在 Linux 系统下包含 libhiredis.so 了啊。

然而这样想,是因为我对应头文件和符号表的认知不够准确,符号表和头文件是两个不同的概念,它们在程序链接过程(预处理-编译-汇编-链接)中扮演不同的角色

  1. 头文件:
    头文件是一种包含函数和变量声明、宏定义等信息的文本文件,通常以.h为后缀。头文件包含了对应库或模块中的接口定义,可以用来告知编译器某个函数的原型、结构体的定义等,以便编译器在编译时能够正确地解析和检查代码。使用头文件可以避免重复编写相同的代码,并提供了对外部库或模块的接口描述。
    在你的情况下,如果你已经包含了 libhiredis 的全部头文件,那么编译器可以在编译阶段正确解析你对 libhiredis 的函数和结构体的引用,以便进行类型检查和语法分析。
  2. 符号表:
    符号表是在链接阶段生成的一种数据结构,记录了可执行文件或动态库中的符号信息,包括函数名、变量名和地址等。符号表的作用是在链接阶段解析程序中对其他库或模块的符号引用,并将这些引用与实际的符号地址进行关联。
    当你在程序中调用 libhiredis 中的函数时,编译器会使用符号表来查找该函数的地址。如果在链接阶段找不到对应的符号地址,编译器会报链接错误。

所以需要同时包含 libhiredis 的全部头文件和正确链接 libhiredis 动态库,以确保编译和链接过程的顺利进行。

在链接阶段,编译器只会在可执行文件中留下对动态库的引用,而不会将动态库的函数实现链接到生成的可执行文件中
具体来说,编译器会将动态库的符号表信息记录在可执行文件中,但并不会将动态库的代码复制到可执行文件中。因此,当程序运行时,操作系统会根据可执行文件中的动态库引用信息,动态地加载对应的动态库,将动态库的代码映射到程序的虚拟地址空间中,并根据符号表信息解析动态库中的函数调用。


顺便介绍一下动态库:
动态库(也称为共享库)在编译时并不会被链接到可执行文件中,而是在程序在运行时由操作系统动态加载并链接。
当程序启动时,如果它依赖于某个动态库,操作系统会在内存中加载这个动态库,并将其链接到程序中。这种动态加载和链接的方式使得程序的可执行文件更加轻量级,因为它不包含所有依赖的库的代码,而是在需要时才进行加载。
动态库的优点包括:

  1. 节约内存:多个程序可以共享同一个动态库的代码,减少了重复占用内存的情况。
  2. 灵活性:可以在不重新编译程序的情况下更新动态库,从而修复bug或者提升性能。
  3. 减少可执行文件大小:因为动态库是在运行时加载的,所以可执行文件的大小会更小。

然而,动态库也有一些缺点,比如在程序启动时需要进行动态链接,可能会引起一些额外的开销;另外,由于动态库的版本问题,可能会引起一些兼容性方面的困扰。

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

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

相关文章

【数字图像处理】均值滤波与中值滤波

在数字图像处理中,均值滤波和中值滤波是常见的空间域处理方法,可以用于过滤图像中的噪声。本文主要介绍数字图像均值滤波与中值滤波的基本原理,并记录在紫光同创 PGL22G FPGA 平台的布署与实现过程。 目录 1. 均值滤波与中值滤波 2. FPGA 布署与实现 2.1 功能与指标定义

aardio调用dll中遇到的难点

近期在做的一个项目,需要调用到32位的dll 查看了dll开发给的函数说明,返回的字符是一个指针地址 虽然在arrdio里面调用成功,但是还需要还原成字符,查了很多资料,程度有限,但是还是找到了一篇文章有讲到&…

基于减法平均算法优化概率神经网络PNN的分类预测 - 附代码

基于减法平均算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于减法平均算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于减法平均优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神…

Python----函数的参数----形参(定义函数时编写的),实参(调用函数时传递的)

在函数定义与调用时,我们可以根据自己的需求来实现参数的传递。在Python中,函数的参数一共有两种形式:① 形参 ② 实参 形参:在函数定义时,所 编写 的参数就称之为 形式参数 实参:在函数调用时&#…

审核业务

1.用户点击发帖按钮,进行帖子发布 2.存储到mysql经验贴表中,设置帖子为1待审核状态 3.判断帖子的发布时间,如果发布时间为立即发布,那么直接存储到redis的立即审核队列(list) 4.如果帖子为未来需要发布的…

走进 McDSP - 步入专业音频25周年

McDSP 在专业音频领域已走过 25 个年头。 McDSP 由 Colin McDowell 于 1998 年创立,可用于 Pro Tools、Logic 和 Cubase 等流行数字音频工作站以及 Avid VENUE 现场音响系统的软件和硬件产品中。 为了回顾一些里程碑式的事件,我们将为您带来一部关于公司…

Spring Boot配置文件 Spring日志文件相关的知识

在上文中,小编带领大家创建了一个Spring Boot项目,并且成功的执行了第一个SPring Boot项目(在网页上运行hello world) 那么,本文的主要作用便是带领大家走进:Spring Boot配置文件 && Spring日志文件…

flutter之graphic图表自定义tooltip

renderer graphic中tooltip的TooltipGuide类提供了renderer方法&#xff0c;接收三个参数Size类型&#xff0c;Offset类型&#xff0c;Map<int, Tuple>类型。可查到的文档是真的少&#xff0c;所以只能在源码中扒拉例子&#xff0c;做符合需求的修改。 官方github示例 …

枚举与应用

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 枚举简介 枚举是一种特…

CentOS 7 使用异步网络框架Libevent

CentOS 7 安装Libevent库 libevent github地址&#xff1a;https://github.com/libevent/libevent 步骤1&#xff1a;首先&#xff0c;你需要下载libevent的源代码。你可以从github或者源代码官方网站下载。并上传至/usr/local/source_code/ 步骤2&#xff1a;下载完成后&…

C语言 - 基础

C 语言 1. Hello World #include <stdio.h>int main(int argc, const char *argv[]) {printf("hello world\n");return 0; }注意: 所有的标点符号必须在英文状态下输入单词不要写错注意空格 创建 C语言 程序步骤&#xff1a; 1、创建一个文档&#xff0c;以…

数据同步异常处理,数据同步重试机制(Java)

一、应用场景 在数据同步时&#xff0c;偶尔会出现代码异常之外的问题。例如网络异常、服务器断电… 如果在以上异常片段中&#xff0c;原始数据库新增了一批数据&#xff0c;同步数据库则会丢失这部分数据 二、实现思路 为了解决以上问题&#xff0c;保证原始数据库操作的每…

HCIA-Datacom跟官方路线学习第二部分

通过VLAN技术&#xff0c; 可以将物理的局域网划分成多个广播域&#xff0c; 实现同一VLAN内的网络设备可以直接进行二层通信&#xff0c; 不同VLAN内的设备不可以直接进行二层通信。 第七章 生成树

Springboot 南阳旅游平台-计算机毕设 附源码 31829

Springboot 南阳旅游平台 目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3 论文结构与章节安排 2 南阳旅游平台系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析 2.2 系统功能分析 2.2.1 功能性分析 2.2.2 非功能性分析…

芙蓉花 欣赏

芙蓉&#xff08;Hibiscus mutabilis Linn&#xff09;是一种锦葵科、木槿属植物原名&#xff1a;木芙蓉&#xff0c;别名&#xff1a;芙蓉花、拒霜花、木莲、地芙蓉、华木、酒醉芙蓉。其花或白或粉或赤&#xff0c;皎若芙蓉出水&#xff0c;艳似菡萏展瓣&#xff0c;故有“芙蓉…

Ubuntu服务器/工作站常见故障修复记录

日常写代码写方案文档&#xff0c;偶尔遇上服务器出现问题的时候&#xff0c;也需要充当一把运维工程师&#xff0c;此帖用来记录服务器报错的一些解决方案&#xff0c;仅供参考&#xff01; 文章目录 一、服务器简介二、机箱拆解三、基本操作3.1 F2进入BIOS3.2 F12进入Boot Me…

try异常处理机制代码举例

当我们在编写程序时&#xff0c;往往需要处理可能发生的异常情况&#xff0c;以保证程序的稳定性和可靠性。这时&#xff0c;就可以使用异常处理机制。C中的异常处理机制通过try、catch和throw关键字实现。 异常处理机制基本上遵循以下的流程&#xff1a; 1. 在可能引发异常的…

教你IDEA解决GIT冲突

前言 GIT基本上贯穿我们的开发生涯&#xff0c;之所以要使用git也是有很多优点的 &#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339; 1.通俗易懂点&#xff0c;保存代码不丢失&#xff1a;防止因内存&#xff0c;操…

字符串函数

读取字符串的函数 1.gets()函数 说明&#xff1a;gets函数简单易用&#xff0c;它读取整行输入&#xff0c;直至遇到换行符&#xff0c;然后丢掉换行符&#xff0c;储存其余字符&#xff0c;并在末尾添加一个空字符使其成为一个C字符串。它经常和puts&#xff08;&#xff09;…

从零开始的RISC-V模拟器开发(一)环境搭建

前言 博主这系列文章是跟随中科院吴伟老师的b站公开课&#xff1a;[完结]从零开始的RISC-V模拟器开发第一季2021春季_哔哩哔哩_bilibili 记录的笔记。仅供学习使用&#xff0c;侵删&#xff01; 苦逼的博主现在自己毕设也是要设计类似的东西。哎。我需要做的是给一个现成的 R…