要更深入了解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. 利用站点ip引导提高站点权重的可行方案

    如题,利用站点每天高数额的ip訪问量来提高站点权重,首先在谈论这个话题之前,我举个样例.我们知道想要一个站点权重非常高,首先它站点本身的内容一定是有价值的,而且受大众欢迎的,人们会常常訪问这个站点来寻 ...

  2. Debian 安装记录

    1.蓝色标注是安装的部分或配置的.  作者:http://www.cppblog.com/jinglexy上海体育馆   2.linux 发行版测评网站:www.distrowatch.com   打 ...

  3. Last-Modified和If-Modified-Since

    Last-Modified 是由服务器往客户端发送的 HTTP 头 If-Modified-Since是由客户端往服务器发送的头 基础知识         1) 什么是”Last-Modified”? ...

  4. Orchard运用 - 整合多说评论插件

    曾经我在一随笔讲述如何整合第三方Disqus评论插件,不过这一插件不是本土,对中国客户毕竟有点别扭.比如这一随笔就提到为啥要选择多说 - 另外一个国内比较知名的评论插件. 今天跟大家分享如何用最简单的 ...

  5. Spring定时器XML配置

    spring-task.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&qu ...

  6. 解决Vue用Nginx做web服务器报错favicon.ico 404 (Not Found)的问题

    有多种解决方案 1.vue静态资源 vue中为网页增加favicon的最便捷的方式为使用link标签 <link rel="shortcut icon" type=" ...

  7. OpenGL入门学习(转载)

    说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色 ...

  8. Python基础(12)--模块

    本文地址:http://www.cnblogs.com/archimedes/p/python-modules.html,转载请注明源地址. 模块简介 如果你退出 Python 解释器重新进入,以前创 ...

  9. windows10 Sqlserver卸载 指定账户不存在

    在windows卸载程序时,有时会出现因提示“指定的账户不存在”而无法删除,如下: 这时时候要先选择要删除的项目,进行修复后再进行删除就可以正常删除了

  10. [Angular] Angular Elements Intro

    Make sure install the latest Angular v6 with Angular CLI. Checkout ght Github for the code. 1. Creat ...