![](https://img-blog.csdnimg.cn/36fb9546c3244ce8889b0df72aac519c.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
编译,链接,装载,库
文章平均质量分 94
本专栏的内容是根据《程序员的自我修养-链接,装载,库》一文中的内容,结合工作的经验,按照自己的理解向大家分享。毕竟书中的有些描述还是有一定难度,我会尽最大努力,尽量花费大家20的时间,学习到80的知识。
谢艺华
主要深耕于 linux 后端开发,热衷于体系能力(包括不限于C、C++、linux、编译原理、数据结构和算法、网络、操作系统
)的沉淀,分享工作中重要的知识点和具有代表性的案例分析。
欢迎志同道合的朋友与我一起前进
展开
-
【程序员的自我修养11】栈与函数调用过程
首先我们来看一张Linux进程中经典的内存布局图:内核空间:是操作系统内核运行的区域,它是内核中一个重要的部分,专门为内核以及与内核直接相关的操作和进程提供服务。用户空间无法直接访问内核空间。栈栈用于维护函数调用的上下文。离开了栈,函数调用就无法实现。栈通常在用户空间的最高地址处分配,通常大小为8M。往地址方向生长。堆:堆是用来容纳应用程序动态分配的内存区域,当程序使用malloc或new分配内存时,得到的内存来自堆里。往高地址生长。动态库:用于程序运行时,动态链接器或在程序运行过程中通过。原创 2024-01-16 11:30:17 · 593 阅读 · 1 评论 -
【程序员的自我修养10】动态库的兼容问题——GLIBC_2.34‘ not found
前几章,花了较大篇幅介绍了动态库链接过程原理,需要面对的场景以及解决思路,真真切切的了解到动态库的优秀之处。这就导致大量开始程序使用动态链接。随着系统中的动态库越来越多,也会出现一些问题。本文介绍动态库的发展过程中遇到的问题,以及如何解决的。以及非常好用的调试tips。本文花了较大篇幅介绍了动态库如何解决和避免兼容性问题,以及分享两个分享实用的环境变量LD_PRELOADLD_DEBUG,至此关于动态库的分享算是结束了。下一章节,我们开始向《库与运行库》进军。若我的内容对您有所帮助,还请关注我的公众号。原创 2024-01-10 20:53:05 · 2521 阅读 · 2 评论 -
【程序员的自我修养09】动态链接过程的场景补充及其思考
通过上一篇【程序员的自我修养08】精华!!!动态库的由来及其实现原理,大致介绍了动态链接的历史背景,以及通过示例进一步了解当今动态库的实现过程。由于篇幅有限,所以针对一些特殊场景和动态库链接的过程没有进一步展开描述。本文主要作为上文内容的补充。本文是对上篇文章的补充,讲解了共享模块中全局变量的处理方式,以及如何实现共享模块中数据段的地址无关性。共享对象全局符号介入。坑惨啦!!!——符号冲突案例分析若我的内容对您有所帮助,还请关注我的公众号。不定期分享干活,剖析案例,也可以一起讨论分享。原创 2024-01-04 09:15:33 · 926 阅读 · 1 评论 -
【程序员的自我修养08】精华!!!动态库的由来及其实现原理
通过前文的讲解,我们大致了解将程序加载到内存的过程。程序与虚拟内存空间映射表虚拟内存空间与物理内存映射表。之后在程序运行过程中,通过不断触发页错误,持续将相应程序页加载到内存中,从而保证进程正常运行。似乎一切都已经完备了。的确,在早期的程序开发中,源文件经过编译生成可重定位文件(.o文件),再经过静态链接生成可执行的ELF文件,最终运行时,通过页加载和页错误的方式,保证进程的正常运行。已经能够满足当时程序的研发,大家开发和使用都非常方便。但是随着IT行业的发展,原先静态链接方式的缺点也逐渐显露。原创 2024-01-03 09:13:10 · 1139 阅读 · 0 评论 -
【程序员的自我修养07】程序的装载过程——小内存如何运行大程序
经过前几篇文章的介绍,我们已经大致了解多个源文件如何编译生成可执行文件的过程。但是程序只有放在内存中才能被CPU执行,本章节向大家介绍,如何程序加载到内存中的过程。小内存如何运行大程序?本文讲述了程序加载到内存的步骤,其实质就是建立两个映射。一、虚拟空间和物理内存的映射关系;二、虚拟空间和程序的映射关系。进程运行过程中通过不断触发页错误,将程序中的页加载到内存中。从而解释了小内存运行大程序的原理。本文介绍了静态链接过程一些特殊场景和优化项。希望大家能够结合自己的实际工作,应用起来。原创 2024-01-03 09:11:42 · 1044 阅读 · 0 评论 -
【程序员的自我修养06】静态链接过程的思考
经过前两章的介绍,我们应该大致掌握了.o文件静态链接为可执行文件的过程。相同的符号定义在多个源文件中,符号解析流程是如何处理方式的呢?无用代码是如何处理的呢?链接的过程,可以控制函数初始化的过程吗?本文则进一步分析,探讨上述几个问题,希望能够给你的工作带来帮助。我们知道不同的.o文件在链接之前是不知道其它.o文件的内容,因此它们之间若存在相同的符号,也是只有在链接阶段才能发现。若链接器发现同一个符号有多处定义,它又是如何处理的呢?两个或两个以上强符号;原创 2023-12-14 15:44:14 · 1144 阅读 · 4 评论 -
【程序员的自我修养05】符号修正的功臣——重定位表
在上篇文章【程序员的自我修养04】目标文件生成可执行文件过程空间与地址分配符号解析和重定位。建议读者看一遍上文,方便理解本章内容。在上篇文章的最后,并提出了一个思考题:链接器是如何知道哪些符号需要被修正的呢?从上文中,我们知道对外部引用的符号或变量,目标文件暂时会设置成0,待符号分析完成后,可执行程序已经确认其真实的虚拟地址,再进行修正。我们是否可以根据变量值是否为0来进行修改正呢?这样的思路,对于函数引用好像是可以的,毕竟没有哪个函数的地址是0吧。原创 2023-12-13 17:39:07 · 1067 阅读 · 2 评论 -
【程序员的自我修养04】目标文件生成可执行文件过程
在前两章的内容中,我们已经了解目标文件的基本布局以及部分局部细节,单独的可执行文件并没有什么实际作用。我们需要多个目标文件链接成可执行文件,或生成动态库。接下来的几章,我会详细介绍目标文件链接成可执行文件的过程,希望大家能够坚持,坚持必有所获。本章节概述了目标文件链接成可执行文件的过程。由如何合并多个目标文件开始,了解到相似段合并的优点。空间与地址分配符号解析和重定位。并用示例分析其过程。内容较多,希望读者能够自己本地操作一遍,认真思考,推敲。若有疑问,也可与我沟通。原创 2023-12-12 20:27:14 · 1234 阅读 · 3 评论 -
【程序员的自我修养03】深入了解ELF文件格式
我们知道链接器在处理目标文件时,需要对目标文件中某些部位进行重定位,即代码段和数据段中哪些绝对地址的引用需要修改。我们知道不同文件间对函数、变量之间的引用,其实就是对符号的引用。之后再介绍常见的段,代码段,数据段,bss段,符号表等内容,以及工作中可以借鉴的地方。:用16进制打印了.text、.data、.rodata、.comment、.eh_frame段的信息,其长度与段表中显示的长度是一一对应的。综上所述,我们基本已经了解了ELF文件格式的布局,接下来,我们尝试深入了解各个段的内容。原创 2023-11-30 18:05:38 · 1440 阅读 · 0 评论 -
【程序员的自我修养02】初识ELF文件格式
正如其专栏名,本专栏主要分享学习《程序员的自我修养——链接、装载与库》的知识点以及结合自己的工作经验以及思考。若你希望与一群志同道合的朋友一起学习,也希望加入到我们的学习群中。本章介绍了linux平台下可重定位文件,动态库文件,可执行文件的存储格式都是ELF类型。也欢迎加入我们的讨论组群。它与目标执行平台大小端无关,它的作用是告诉目标执行平台,本文件的代码段,数据段的存储方式,用于解析。下一章,我们再通过了解段表,更进一步了解ELF文件的内容布局。可执行文件的入口地址在文件的偏移0x540地址。原创 2023-11-30 10:23:02 · 1301 阅读 · 2 评论 -
深思:C与C++相互调用问题
简单沟通下,才知道他遇到了一个工程编译的问题,一直无法编译通过,困扰了他快一天时间。在历史的长河中,先辈们发现随着项目工程的扩大,很容易出现不同模块定义了相同的全局变量或对外函数,导致符号相同的情况。我相信有经验的朋友肯定已经知道问题的原因了,但是对于未接触相关案例的同学,估计还是一头雾水,特别是一直从事C语言开发的工程师,估计还不清楚发生了什么。,因此会导致C++ 认知中A.h 的符号与 A.o的实际符号不匹配,虽然动态库libB.so 已经能生成,但是在链接阶段,符号重定位时,就会出现。原创 2023-11-27 17:09:32 · 1288 阅读 · 0 评论 -
【程序员的自我修养01】编译流程概述
在大型的工程项目中,随着需求的迭代代码分支也比较多,经常会用到类似"if"、"#ifdef"、"#elif"、"#else"、"#endif" 等分支控制方式。答:我们在工作中,经常会遇到一些问题,需要查看动态库的信息,比如查看依赖库,反汇编,甚至是gdb调试。以上便是本文的内容,我们回顾了编译的四大过程:预处理,编译,汇编,链接。在一般应用中,不会逃逸的局部对象所占用的比例很大,如果能在编译器优化时,为其在栈上分配内存空间,那大量的对象就会随着方法结束而自动销毁了,也欢迎加入我们的讨论组群。原创 2023-11-25 18:04:59 · 1197 阅读 · 0 评论 -
坑惨啦!!!——符号冲突案例分析
如上可知,我们遇到的问题并不是显示符号冲突,因为显示符号冲突是在编译阶段就已经确认,并且会一直存在。隐式符号冲突会导致程序运行时跳转到错误的符号,进而执行错误的代码段,最终造成错误。我们知道静态其实就是目标文件.o的集合体,只有当可执行程序需要时,才会从静态库中提取出相关依赖的.o文件,进行编译。,该参数告诉链接器,将该参数后面的共享库强制编译到目标文件中,即将共享库中的代码段,数据段强制加入到可执行程序中。通过以上分析,我觉得在项目中,我们可以从预防和解决两个方面规避符号冲,导致程序非预期情况。原创 2023-11-21 18:01:42 · 327 阅读 · 1 评论