要更深入了解C++, 必需要知道一个程序从開始到结束都干了些什么, 怎么干的。

所以我从C++编译到执行过程,解析下程序是怎么跑的。

首先,初略的说一下之前C++的编译过程。C++编译过程包含预编译-》汇编-》编译-》链接。称为一个可运行文件。(Windows平台下为.exe文件)。

预编译主要展开包括的头文件,宏定义等操作。比如一个简单的main程序,编译预编译后,的文件对照。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center">

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center"> 
能够看到里面的宏已经被去掉了。

假设定了那个宏。那么宏里面的内容也会显示出来。头文件也是。假设你包括了你一个.h 文件,那么整个.h文件会包括进来。

汇编过程,就是把已经预编译的文件编译成汇编代码的过程。整个过程会包括语法,词法的分析,和一些优化操作。

编译过程事实上是跟汇编能够合成一个阶段,变成目标代码。也就是二进制文件。

链接过程是将单个编译后的文件链接成一个可运行程序。前面的预编译、汇编、编译都是正对单个文件,以一个文件为一个编译单元,而链接则是将全部关联到的编译后单元文件和应用的到库文件。进行一次链接处理,之前编译过的文件 假设实用到其它文件中面定义到的函数。全局变量。在这个过程中都会进行解析。

首先看看编译后的文件样子(已VS2012编译后的OBJ文件为样例。不同编译器 样式可能会不同。

编译前的文件

#include "Car.h"

int main(int argc, char* argv[])

{

 Car* p = new Car();

delete p;

 return 1;

}

编译后的样子(因为编译后的文件 信息太多 仅仅贴出里面未解析符号部分。

UNDEF:00002DC4 ; int __thiscall Car::Car(Car *__hidden this)

UNDEF:00002DC4                 extrn

?

0Car@@QAE@XZ:near">
?

?

0Car@@QAE@XZ:near ; CODE XREF: _main+63p

UNDEF:00002DC8 ; int __thiscall Car::~Car(Car *__hidden this)

UNDEF:00002DC8                 extrn ??

1Car@@QAE@XZ:near

UNDEF:00002DC8                                         ; CODE XREF: Car::`scalar deleting destructor'(uint)+26p

UNDEF:00002DCC ; __fastcall _RTC_CheckStackVars(x, x)

UNDEF:00002DCC                 extrn @_RTC_CheckStackVars@8:near

UNDEF:00002DCC                                         ; CODE XREF: std::_String_alloc<0,std::_String_base_types<char,std::allocator<char>>>::_Alloc_proxy(void)+68&#24;p

UNDEF:00002DCC                                         ; $LN19+72&#24;p ...

UNDEF:00002DD0 ; __fastcall __security_check_cookie(x)

UNDEF:00002DD0                 extrn @__security_check_cookie@4:near

UNDEF:00002DD0                                         ; CODE XREF:

$construct@PADAAPAD@?

$allocator@D@std@@QAEXPAPADAAPAD@Z+F&#24;p">
__ehhandler$??$construct@PADAAPAD@?$allocator@D@std@@QAEXPAPADAAPAD@Z+F&#24;p


UNDEF:00002DD0                                         ;

$allocator@U_Container_proxy@std@@@std@@QAEXPAU_Container_proxy@1@$$QAU21@@Z+F&#24;p">
__ehhandler$??

$construct@U_Container_proxy@std@@U12@@?$allocator@U_Container_proxy@std@@@std@@QAEXPAU_Container_proxy@1@$$QAU21@@Z+F&#24;p ...

UNDEF:00002DD4 ; __stdcall _CxxThrowException(x, x)

编译后的文件用(用反汇编成汇编代码查看) 当中实现函数会变成一堆汇编指令。而那些引用到的在其它文件中面实现的函数将会变成一个特点的符号(如上面中的调用Car类的构造函数 extrn
??0Car@@QAE@XZ:near)这些符号称做为解析的符号。表示在链接的时候须要被解析。

符号的生成名称详细跟编译器有关,可是会保证一个类的某个函数名称在同一个编译里面必须是唯一的,由于我们在预编译阶段已经把Car.h包括进来所以编译器能正确生成这个函数的名字。然后在链接的时候 会找到改名字的函数,把此标识名字替换为函数的地址。这样就实现的链接。

在符号解析(symbol resolution)阶段,链接器依照全部目标文件和库文件出如今命令行中的顺序从左至右依次扫描它们。在此期间它要维护若干个集合:(1)集合E是将被合并到一起组成可运行文件的全部目标文件集合。(2)集合U是未解析符号(unresolved symbols,比方已经被引用可是还未被定义的符号)的集合。(3)集合D是全部之前已被增加到E的目标文件定义的符号集合。一開始,E、U、D都是空的。

(1): 对命令行中的每个输入文件f,链接器确定它是目标文件还是库文件,假设它是目标文件。就把f增加到E,并把f中未解析的符号和已定义的符号分别增加到U、D集合中。然后处理下一个输入文件。



(2): 假设f是一个库文件,链接器会尝试把U中的全部未解析符号与f中各目标模块定义的符号进行匹配。假设某个目标模块m定义了一个U中的未解析符号,那么就把 m增加到E中,并把m中未解析的符号和已定义的符号分别增加到U、D集合中。不断地对f中的全部目标模块反复这个过程直至到达一个不动点(fixed point),此时U和D不再变化。而那些未增加到E中的f里的目标模块就被简单地丢弃,链接器继续处理下一输入文件。



(3): 假设处理过程中往D增加一个已存在的符号,或者当扫描全然部输入文件时U非空。链接器报错并停止动作。否则,它把E中的全部目标文件合并在一起生成可运行文件。



C++ 编译,执行过程 具体解释。的更多相关文章

  1. C程序编译执行过程

    C程序编译执行过程   认识C编译执行过程,是C学习的开端. 简单说C语言从编码编译到执行要经历一下过程:   C源代码 编译---->形成目标代码,目标代码是在目标机器上运行的代码. 连接-- ...

  2. c语言编译执行过程

    <h4>认识C编译执行过程</h4>认识C编译执行过程,是C学习的开端.简单说C语言从编码编译到执行要经历一下过程: C源代码编译---->形成目标代码,目标代码是在目标 ...

  3. C#编译执行过程

    前言 大家好,我是卫斯理(Wesley).喜欢武侠的朋友可能知道小说中也有个卫斯理,他是位冒险家,财力充沛,极富冒险精神,并且有着超强的好奇心,对奇异的事情总有"打破沙锅问到底"的 ...

  4. go 编译:交叉编译&编译执行过程

    1. 交叉编译 编译Windows程序和mac程序 GOOS=windows GOARCH-amd64 go build main.go 转自:https://www.cnblogs.com/mafe ...

  5. C#在.NET编译执行过程

    1..NET语言的编译器接受源代码文件,并生成名为程序集的输出文件. 程序集要么是可执行的,要么是DLL 程序集里的代码并不是本机代码,而是一种名称为CIL的中间语言 程序集包含如下信息: 程序的CI ...

  6. Java编译执行过程

    在刷软件设计师中级考试的题目,判断关于编译系统对某高级语言进行翻译的叙述的对错.记得刚开始学Java的时候自己就觉得自己对程序的执行过程理解的相当的透彻,但是一对答案,我的小心脏就有点受不了了,特此在 ...

  7. angualar入门学习-- 自定义指令 指令编译执行过程

    3个阶段: 一.加载阶段 加载angular.js的源码,找到ng-app确定应用边界范围. 二.编译阶段 compile 查找所有指令,保存在一个列表中 对所有指令按优先级(property属性值) ...

  8. java代码的编译执行过程

  9. C C++ Java C# JS编译、执行过程的原理入门分析

    C.C++是典型的编译型编程语言,编译链接后,点击则可执行. JS,解释型脚本语言,则不需要进行编译,直接解释执行. Java和C#则是所谓的高级语言,编译执行的方式做了很多处理, 尤其是C#,VS编 ...

随机推荐

  1. Android SDK Manager 代理服务器设置

    http://blog.csdn.net/star_splendid/article/details/6939063 自己机子更新的话,速度1KB/s 实在是等不及了~找方法吧 http://www. ...

  2. gdb 与函数过程

    http://www.lenky.info/archives/2013/02/2202

  3. Skip-External-Locking – MySQL性能参数详解

    MySQL的配置文件my.cnf中默认存在一行skip-external-locking的参数,即“跳过外部锁定”.根据MySQL开发网站的官方解释,External-locking用于多进程条件下为 ...

  4. ArcGIS for Android地图上实际距离与对应的屏幕像素值计算

    本篇文章主要介绍了"ArcGIS for Android地图上实际距离与对应的屏幕像素值计算",主要涉及到ArcGIS for Android地图上实际距离与对应的屏幕像素值计算方 ...

  5. 将Linux代码移植到Windows的简单方法

    一.前言 Linux拥有丰富各种源代码资源,但是大部分代码在Windows平台情况是无法正常编译的.Windows平台根本无法直接利用这些源代码资源.如果想要使用完整的代码,就要做移植工作.因为C/C ...

  6. 【翻译自mos文章】job 不能自己主动运行的解决方法

    job 不能自己主动运行的解决方法 參考原文: Jobs do not execute automatically (Doc ID 309945.1) 适用于: Oracle Server - Ent ...

  7. spm教程

    1.spm初学者教程:http://www.ernohermans.com/wp-content/uploads/2011/11/spm8_startersguide.pdf 2.spm官方mannu ...

  8. [翻译] PBJNetworkObserver 网络监控

    PBJNetworkObserver 网络监控 https://github.com/piemonte/PBJNetworkObserver Introduction 'PBJNetworkObser ...

  9. 教你用软碟通(UltraISO)刻录系统光盘

    用光盘装系统有几个好处:1.便携,显而易见,这是最大的优点2.大容量,比之维护光盘,可以集成N多维护工具,甚至还可以放下几个ghost镜像3.维护功能强大,因为容量大,可以放更多工具.还可以设置多重启 ...

  10. 如何更改postgresql的最大连接数

    改文件 postgresql.conf 里的 #max_connections=32 为 max_connections=1024 以及另外相应修改 share_buffer 参数.