要更深入了解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. NativeXml: A native Delphi XML parser and writer

    http://www.simdesign.nl/xml.html This software component contains a small-footprint Object Pascal (D ...

  2. Jquery实战——横纵向的菜单

    横纵向的菜单效果,点击纵向菜单显示其子菜单.鼠标指向横菜单的时候.显示其子菜单,鼠标离开,子菜单隐藏. HTML代码: <span style="font-size:18px;&quo ...

  3. HDU 2896 病毒侵袭 【AC自动机】

    HDU 2222 仅仅求出了和文本串匹配的模式串个数,本题要求求出匹配的模式串的编号. 不同的部分在代码中的注释部分. #include <cstdio> #include <cst ...

  4. vc维的解释

    在做svm的时候我们碰到了结构风险最小化的问题,结构风险等于经验风险+vc置信范围,当中的vc置信范围又跟样本的数量和模型的vc维有关,所以我们看一下什么是vc维 首先看一下vc维的定义:对一个指标函 ...

  5. Android内存调试命令

    adb shell dumpsys meminfo 包名 比如: adb shell dumpsys meminfo cn.com.test

  6. C语言宏定义和宏定义函数

    要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定 ...

  7. Django admin管理

    admin的配置 admin是django强大功能之一,它能共从数据库中读取数据,呈现在页面中,进行管理.默认情况下,它的功能已经非常强大,如果你不需要复杂的功能,它已经够用,但是有时候,一些特殊的功 ...

  8. 转载 C++实现的委托机制

    转载 C++实现的委托机制 1.引言 下面的委托实现使用的MyGUI里面的委托实现,MyGUI是一款强大的GUI库,想理解更多的MyGUI信息,猛击这里http://mygui.info/ 最终的代码 ...

  9. ECharts学习总结(一):ECharts的第一个图表

    在进行echarts图表开发之前先要到echarts官网下载echarts的库文件,我下载的是echarts-2.2.7.然后把库文件放到工程文件web目录下.接下来进行第一个图表的显示步骤如下: 1 ...

  10. [Python爬虫] 之一 : Selenium+Phantomjs动态获取网站数据信息

    本人刚才开始学习爬虫,从网上查询资料,写了一个利用Selenium+Phantomjs动态获取网站数据信息的例子,当然首先要安装Selenium+Phantomjs,具体的看 http://www.c ...