1代码

点击查看代码
**sum.cpp**
int gdata=10;
int sum(int a,int b){
return a+b;
} **main.cpp** extern int gdata;
int sum(int , int );
int data=20;
int main(){
int a =gdata;
int b=data;
int ret=sum(a,b);
return 0;
}

1:编译

需要关注的几个点

1: .o 文件的格式组成是什么样子?

2: .exe 文件的组成格式是什么样子?

3: "所有.o文件段的合并 符号表合并后,进行符号解析"

4: "符号的重定位(重定向)"

5: "符号表的输出"=> "符号"

6: 符号什么时候分配虚拟地址?

预编译

以#开头的命令

除#pragma lib -> 链接阶段处理

除#pragma link -> 链接阶段处理

编译

语法分析,语义分析,代码优化 gcc g++

编译后生成相应平台的 汇编代码 X86 和 AT&T

链接

链接所有 .o文件和 静态库文件

.o 文件 主要是由以下组成

elf 文件头

.text

.data

.bss

.symbal

.section table

....

符号表中,在自己文件中定义的,那就是符号定义,如果是引用外部的就 是 "UND"符号引用

符号表中的符号 都没有分配地址,如下图,所以编译过程中,符号是不分配虚拟地址的,是在链接的时候分配

经过了上面的 预编译-》编译-》汇编 各个阶段后 下面开始进入了 链接阶段

main.o 文件 sum.o 文件

上面我们看到 .o 文件是由各个段组成的,所以进入链接阶段的时候

第一步 将各个.o 文件 的各个段合并

main.o 文件的 .text段 与 sum.o 文件的 .text 段合并

main.o 文件的 .data段 与 sum.o 文件的 .data 段合并

main.o 文件的 .bss段 与 sum.o 文件的 .bss 段合并

main.o 文件的 符号表 与 sum.o 文件的符号表 段合并

第二步 非常重要的一点是 在main.o文件的符号表与sum.o文件的符号表段合并的时候,需要进行符号解析

什么是"符号解析"?

所有对符号的引用,都要找到该符号定义的地方 “符号的引用” 即符号为 UND形式, 要找到该符号定义的地方即要找到该符号是在.text 段中定义还是在.data段中定义,

例如:链接器发现main.o文件的sum函数和gdata是UND形式的,那么链接器会去其他文件中找到sum和gdata的定义,如果没找到,那么链接器报错"符号未定义",

如果链接器找到了多个,那么链接器也会报错 “符号重定义”,所以在整个工程中,全局的名字是不能重名的,否则会产生冲突.

符号解析成功以后 就开始回给所有的符号分配地址

第三步 "符号重定向"

在符号解析成功以后并且给所有的符号分配地址后,需要继续做 "符号重定向"

在我们指令编译汇编生成.O文件的时候,生成的指令中的符号的地址都是用0 代理,如下图

现在我们需要将给符号分配好的地址 将指令中的这些0地址重新修正

现在我看下链接后的情况

符号表情况

指令情况

所以现在我们知道 “符号是在什么时候分配地址”, 在链接第一阶段 符号解析成功后

可执行文件 a.out 和 .O文件的组成方式很像,但是还是有一点区别

在a.out 可执行文件中 增加了 “program headers” , a.out 文件中不是 所有的内容都会加载到内存中的,这个

"program headers"中指定了需要加载哪些到内存中

上图中的 有两个load 就是需要加载到内存中的.


下面我们再看看可执行程序加载到内存过程

<三>从编译器角度理解C++代码编译和链接原理的更多相关文章

  1. Linux | GCC如何实现代码编译&&汇编&&链接过程

      正文: 每次我们程序员所写的 代码 是给程序员看的呢?还是给电脑看的?其实我们所写的代码只是我们程序员之间交流的一样特殊语言,电脑是看不懂的.那么我们如何实现人机交流呢?这就不得不请出我们我们今天 ...

  2. C++模板声明与实现分开--由此想到的编译,链接原理

    参考了以下两篇文章: C++编译链接原理简介  语言程序编译过程 2 问题来源:当模板文件的实现与声明分开在不同文件中时,链接时会提示找不到相应模板函数,如下 一,编译和链接的大概原理: 1,编译,遍 ...

  3. 从编译器角度理解C++中的引用和指针

    欲分析指针和引用,则要分析变量名和地址之间的关系(不管你理解还是不理解,无论你是从老师那里听到的,还是网上看到的,应该都知道两句话:1. 指针就是地址,2.引用就是给变量起个别名) 所以我们就要来分析 ...

  4. 多态原理探究-从C++编译器角度理解多态的实现原理

    理论知识: 当类中声明虚函数时,编译器会在类中生成一个虚函数表. 虚函数表是一个存储类成员函数指针的数据结构. 虚函数表是由编译器自动生成与维护的. virtual成员函数会被编译器放入虚函数表中. ...

  5. 小师妹学JVM之:深入理解JIT和编译优化-你看不懂系列

    目录 简介 JIT编译器 Tiered Compilation分层编译 OSR(On-Stack Replacement) Deoptimization 常见的编译优化举例 Inlining内联 Br ...

  6. 如何提升代码编译的速度 iOS

    前阵子有遇到代码编译速度慢的问题,特别是在swift和object-c混编的过程中问题很突显. 网上找到一篇蛮好的文章里面又一些解决方法 推荐一下 http://www.open-open.com/l ...

  7. Linux - Unix环境高级编程(第三版) 代码编译

    Unix环境高级编程(第三版) 代码编译 本文地址:http://blog.csdn.net/caroline_wendy 时间:2014.10.2 1. 下载代码:http://www.apuebo ...

  8. 编译器角度看C++复制构造函数

    [C++对象模型]复制构造函数的建构操作 关于复制构造函数的简单介绍,可以看我以前写过的一篇文章C++复制控制之复制构造函数该文章中介绍了复制构造函数的定义.调用时机.也对编译器合成的复制构造函数行为 ...

  9. 第6章 Python中的动态可执行方法 第6.1节 Python代码编译

    在介绍动态可执行方法前,本节先介绍一下Python代码编译有关的知识,因为部分内容和动态执行有些关联. 一.    Python解释器的功能 Python虽然是解释型语言,但Python代码也是可编译 ...

随机推荐

  1. TechEmpower 21轮Web框架 性能评测 -- C# 的性能 和 Rust、C++并驾齐驱

    自从2021年2月第20轮公布的测试以后,一年半后 的2022年7月19日 发布了 TechEmpower 21轮测试报告:Round 21 results - TechEmpower Framewo ...

  2. 精心总结十三条建议,帮你创建更合适的MySQL索引

    上篇文章讲到使用MySQL的Explain命令可以分析SQL性能瓶颈,优化SQL查询,以及查看是否用到了索引. 我们都知道创建索引可以提高查询效率,但是具体该怎么创建索引? 哪些字段适合创建索引? 哪 ...

  3. Java-面向对象三大特征、设计规则

    1)封装: 1.1)类:封装的是对象的属性和行为 1.2)方法:封装的是具体的业务逻辑实现 1.3)访问控制修饰符:封装的是访问的权限 2)继承: 2.1)作用:代码的复用 2.2)父类/基类:共有的 ...

  4. MySQL-报错:Error when bootstrapping CMake:

    在进行MySQL的源码安装的时候,系统上找不到合适的C编译器,GCC忘了装,莫慌,直接  yum命令装上gcc,还有gcc-C++没装的话后面也会提示错误,一起装上,,, [root@localhos ...

  5. Python小游戏——外星人入侵(保姆级教程)第一章 05重构模块game_functions

    系列文章目录 第一章:武装飞船 05:重构:模块game_functions 一.重构 在大型项目中,经常需要在添加新代码前重构既有代码.重构旨在简化既有代码的结构,使其更容易扩展.在本节中,我们将创 ...

  6. 人人都能看懂的卡西欧fx991cnx玩机指南,手把手教你如何利用计算器的漏洞爆机

    专业术语说明 你是VerB还是VerC 别人问你这个问题的时候不要慌,帮你看你的计算器是Ver几: 同时按住shift.7.开机键 9 5次shift 第一行后半句即是 紧接着可以顺便看看计算器的序列 ...

  7. 刷题记录:Codeforces Round #724 (Div. 2)

    Codeforces Round #724 (Div. 2) 20210713.网址:https://codeforces.com/contest/1536. div2明显比div3难多了啊-只做了前 ...

  8. Mybatis的ResultMap与limit分页查询

    ResultMap主要解决的是:属性名和字段不一致 如果在pojo中设置的是一个名字,在数据库上又是另一个名字,那么查询出来的结果或者其他操作的结果就为null. //在pojo中 private S ...

  9. FusionCopmpute之CNA,VRM虚拟机安装

    CNA和VRM安装步骤一样,需要修改的只有IP 按步骤创建 修改自己虚拟机想要存放的位置 需要把自己网络同样配置为仅主机(提前配好) 自己也可以修改至200G 虚拟机只是用多少取多少 CNA可以设置为 ...

  10. 关于MicroPython mpremote工具 的一些用例,闲聊

    关于MicroPython mpremote工具 的一些用例,闲聊 我尝试了很多不同的第三方micropython工具,有些是Windows应用程序,有些是VScode插件. 但是当我尝试过Micro ...