zoukankan      html  css  js  c++  java
  • C++的编译与连接

    编译器的任务是把我们人类通常能够读懂的文本形式的 C 语言文件转化成计算机能明白的目标文件。
    1.  预编译
    生成的仍然是.c文件
    1)把"include"的文件拷贝到要编译的源文件中。
    2)用实际值替代"define"的文本。
    3)在调用宏的地方进行宏替换。

    2.  编译
    这个过程是用于生成汇编语言,.asm文件。

    3.  生成目标文件
    .o文件,包含了以下两项内容

    • 代码:对应着 C 文件中函数的定义
    • 数据:对应着 C 文件中全局变量的定义(对于一个已初始化的全局变量,它的初值也存于目标文件中)。

    编译器会留个空白(blank),这个“空白”(我们也称之为“引用”(reference))拥有与之相关联的一个名字,但该名字对应的值还尚未可知。

    链接器的任务是连接变量/函数的名字与变量/函数的定义,生成可执行文件。

    如果不能连接,就会抛出external error

    初始化变量已经提前赋予了某个特定的初值,这些值同时保存于目标文件和可执行文件中。当程序开始运行时,操作系统将这些值拷贝至内存中一块名为数据段(data segment)的区域;对未初始化变量,操作系统假设其初值均为0, 因此没有必要对这些值进行拷贝,操作系统保留一部分全为0内存空间,我们称其为 bss 段(bss segment)。

    局部变量的生命周期只存在于程序运行之时,所以链接器无需处理。他们存储在栈或堆中,由于堆和栈在程序运行过程中都会动态地改变大小,通常的处理方式是让栈从一个方向向另一个方向增长,而堆则从另一端增长。

    :如果有很多不同的程序都需要做一些相同的操作(例如将输出打印到屏幕上,从硬盘读取文件等),那么所有相关的目标文件集合都统一存放在一个方便访问的地方,这个地方就称为库

    静态库(static library),在Windows平台上,静态库的扩展名为 .LIB,可用 .LIB 工具生成。

    缺点1:循环依赖。

    从静态库中导入文件的粒度:如果某个特定符号的定义是必须的,那么包含该符号定义的整个目标文件(不是整个静态库)被导入。

    库的处理顺序。链接器按命令行从左到右的顺序进行处理,只有前一个库处理结束了,才会继续处理下一个库。换句话说,如果后一个库中导入的目标文件依赖于前一个库中的某个符号,那么链接器将无法进行自动关联,导致链接失败。

    缺点2:一旦程序完成静态链接后,代码就永久保持不变了,如果万一有人发现并修复了 printf 中的某个bug,那么所有使用了printf的程序都不得不重新链接才能应用上这个修复。

    缺点3:所有可执行文件都要存储一份如printf,fopen这类常用函数的拷贝,将占用大量的硬盘空间。

    共享库(Shared libraies),其扩展名在 Unix 系统中为 .so,在 Windows 系统中为 .dll,在Mac OS X系统中为 .dylib。

    优点1:链接的粒度(the granularity of the link)。

    如果程序中只引用了共享库里的某个符号(比如,只使用了 libc.so 库中的 printf),那么整个共享库都将映射到程序地址空间中,之后可自行解决相互引用问题。并且,库内的符号集中保存在一片连续的空间里。

    优点2:链接完后改变的代码,在运行时会生效。

    优点3:对于共享库,链接器没有必要将所有的符号都关联起来,而是贴上一个“我欠你(IOU)”这样的标签,直到程序真正运行时才对贴有这样标签的内容进行处理。

  • 相关阅读:
    Unique Binary Search Trees 解答
    Unique Paths II 解答
    Unique Paths 解答
    Maximum Subarray 解答
    Climbing Stairs 解答
    House Robber II 解答
    House Robber 解答
    Valid Palindrome 解答
    Container With Most Water 解答
    Remove Duplicates from Sorted List II 解答
  • 原文地址:https://www.cnblogs.com/qionglouyuyu/p/4181522.html
Copyright © 2011-2022 走看看