要更深入了解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. Cascode MOSFET increases boost regulator's input- and output-voltage ranges

    Targeting use in portable-system applications that require raising a battery's voltage to a higher l ...

  2. 将DLL挂接到远程进程之中(远程注入)

    线程的远程注入 要实现线程的远程注入必须使用Windows提供的CreateRemoteThread函数来创建一个远程线程该函数的原型如下:HANDLE CreateRemoteThread(    ...

  3. Virtual Treeview - Paint cycles and stages

    The most complex process in Virtual Treeview is without doubts its painting. Read here what stages V ...

  4. IPC low/medium/high density 什么意思?

    http://wiki.altium.com/pages/viewpage.action?pageId=3080344 Land Pattern Information Density Level A ...

  5. C语言跟内存分配方式-alloc malloc calloc

    转载:http://blog.csdn.net/ubuntulover/article/details/7581317 (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整 ...

  6. redis中文API

    1.学习文档地址:http://www.redisdoc.com/en/latest/index.html 2.redis中文API REDIS所有的命令 <<ABOUT LIST> ...

  7. python的__slots__节约内存的魔法;检查python每一行代码内存占用情况的工具

    在Python中,每个类都有实例属性.默认情况下Python用一个字典来保存一个对象的实例属性.这非常有用,因为它允许我们在运行时去设置任意的新属性. 然而,对于有着已知属性的小类来说,它可能是个瓶颈 ...

  8. GPGPU OpenCL 精确字符串查找

    字符串查找是信息安全.信息过滤领域的重要操作,尤其是对大文本的实时处理.这篇作为实例,使用GPU OpenCL进行精确模式串查找. 1.加速方法 (1)将少量常量数据,如模式串长度.文本长度等,保存在 ...

  9. win8自带输入法如何切换全角、半角操作流程

    原文参考:http://jingyan.baidu.com/article/066074d6620c45c3c21cb0d3.html 曾经不知道怎么切换半角全角的时候非常抓狂(原因是不知道是半角全角 ...

  10. java学习笔记14--多线程编程基础1

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note14.html,转载请注明源地址. 多线程编程基础 多进程 一个独立程序的每一次运行称为 ...