要更深入了解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. 数论E - Biorhythms(中国剩余定理,一水)

    E - Biorhythms Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Subm ...

  2. hdu 1272 小希的迷宫(java实现)

    小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  3. ThinkPHP:入门安装 (1)

    1.下载ThinkPHP包 2.引入ThinkPHP.php创建目录文件, 默认ThinkPHP框架所在文档目录 <?php //加载框架入口文件 require './ThinkPHP/Thi ...

  4. CentOS6.5配置网络

    [ CleverCode发表在csdn博客中的原创作品,请勿转载.原创地址:http://blog.csdn.net/clevercode/article/details/46376985] 1 网卡 ...

  5. [Linux] Ubuntu下解压rar文件的方法

    一般通过默认安装的ubuntu是不能解压rar文件的,只有在安装了rar解压工具之后,才可以解压.其实在ubuntu下安装rar解压工具是非常简单的,只需要两个步骤就可以迅速搞定. ubuntu 下r ...

  6. SpringMVC之HandlerMethodArgumentResolver和<mvc:argument-resolvers>

    SpringMVC提供了一个HandlerMethodArgumentResolver接口可以让我们处理方法的参数,和注解结合提来,能有很强大的功能,例如SpringMVC提供的@ModelAttri ...

  7. 如何更换Office 2013的product key?

    第一步 第二步 第三步 ... ... ... ... ^_^   参考资料 ======================== Change Product Key Office 2013 Home ...

  8. 【转】svn 的开发目录结构和流程

    原文: https://blog.csdn.net/iteye_15570/article/details/82548132 ------------------------------------- ...

  9. (转)行为树(Behavior Tree)

    转自:http://www.cnblogs.com/konlil/archive/2011/04/23/2025954.html 如果要让游戏里的角色或者NPC能执行预设的AI逻辑,最简单的用IF.. ...

  10. 菜鸟从零学编程——GET与POST

    相信大家在面试的时候经常会被问到:GET与POST有什么区别吧?你是怎么回答的呢?POST比GEt安全?GET有URL的长度限制而POST没有或者很大?GET通过URL或者Cookie传参数,POST ...