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. 利用CSS3自定义属性来为网站添加“暗黑模式”(暗色模式/DarkMode)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_114 究竟什么是暗黑模式?这个概念起初来源于macOS系统,该系统的mojave版本为用户提供两个主题皮肤,即浅色和深色的皮肤.自 ...

  2. MySQL 的prepare使用中的bug解析过程

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 目录 一.问题发现 二.问题调查过程 三.问题解决方案 四.问题总结 一.问题发现 在一次开发中使用 MySQL PREP ...

  3. web监听器解析

    监听器是web三大组件之一,事件监听机制如下: 事件:某个事件,如果初始化上下文 事件源:事件发生的地方 监听器:一个对象,拥有需要执行的逻辑 注册监听:将事件.事件源.监听器绑定在一起.当事件源发生 ...

  4. HTML引用CSS实现自适应背景图

    链接图片背景代码 body {background: url('链接') no-repeat center 0;} 颜色代码 body{background:#FFF} 链接图片背景代码2 <b ...

  5. Docker 搭建 Nexus3 私服 | 基本操作

    1 Docker 安装 Nexus3 1.1 创建目录 在硬盘上创建 Nexus3 的主目录: mkdir -p /Users/yygnb/dockerMe/nexus3 为该目录添加权限: chmo ...

  6. C与C++有什么区别

    C是一个结构化语言,它的侧重点在于算法和数据结构.对语言本身而言,C是C++的一个子集. C程序的设计首要考虑的是如何通过一个过程,对输入进行运算处理,得到输出. 对于C++,首要考虑的是如何构造一个 ...

  7. 华为云计算灾备产品BCManager 及eBackup的组网方式

    BCManager的作用 OceanStor BCManager是面向企业数据中心存储容灾业务的管理软件,实现容灾.双活.两地三中心等容灾环境的管理,具备多种数据库应用与虚拟化环境的容灾管理功能,简单 ...

  8. 如何做raid级别磁盘(rhel和centos系统皆可)

    添加磁盘,自己需要多少磁盘即可添加多少数量 此处只添加了三块200MB大小的磁盘 此处三块磁盘,只有两块做raid,一块与raid磁盘为实验测读写速率,不测速率可三块都做raid. 进入虚拟机给三个磁 ...

  9. JUC锁:核心类AQS源码详解

    目录 1 疑点todo和解疑 2 AbstractQueuedSynchronizer学习总结 2.1 AQS要点总结 2.2 细节分析 2.2.1 插入节点时先更新prev再更新前驱next 2.2 ...

  10. Mac_linux_ssh防掉线

    vi ~/.ssh/config 加入一条 ServerAliveInterval 60 #客户端主动向服务端请求响应的间隔