C++复习

C++分离式编译模式

2018-05-04  本文已影响24人  凉拌姨妈好吃

1. 什么是分离式编译?

一个项目由若干个源文件共同实现,而每个源文件(.cpp)单独编译成目标文件(.obj),最后将所有目标文件连接起来形成单一的可执行文件(.exe)的过程。

---------------test.h-------------------

void f();//这里声明一个函数f

---------------test.cpp--------------

#include”test.h”

void f()

{

…//do something

}  //这里实现出test.h中声明的f函数

---------------main.cpp--------------

#include”test.h”

int main()

{

f(); //调用f,f具有外部连接类型

}

上面程序在编译器内部的过程为:

2. 为什么编译器不能支持对模板的分离式编译?

-------------test.h----------------

template<class T>

class A
{
  public:
      void f(); // 这里只是个声明
};
---------------test.cpp-------------

#include”test.h”

template<class T>

void A<T>::f()  // 模板的实现

{
  …//do something
}
---------------main.cpp---------------

#include”test.h”

int main()

{
  A<int> a;
  f(); // #1
}

上面程序在编译器内部的过程为:


以下内容来自:引用1

3. 静态链接库与动态链接库

3.1 原始的链接方法
/********
* test.c
*********/
#include<stdio.h>
int main()
{
    int num;
    scanf("%d",&num);
    printf("ok %d\n",num);
    return 0;
}

假设printf的代码存在 printf.c,scanf的代码存在scanf.c,翻译之后变为可重定位模块.o


image.png

这种链接形式所存在的问题:

  1. 每次链接都需要显式的列出所有.o文件
  2. 不同程序如果要使用相同的模块,就要将模块链接到相应的程序中,影响效率

为了解决第一个问题,出现了静态链接库

3.2 静态链接库

静态库的核心思想是,将不同的可重定位的模块.o打包成一个文件,在链接的时候会自动从文件中抽取所需要用到的模块,这样就无需手动列出要用的模块

那么这就会出现一个问题:生成的文件比源文件大得多,存在相当大的空间浪费。怎么办呢?这时候就提出了动态链接

3.3 动态链接库

动态链接库的核心思想:代码共享和延迟绑定。代码共享依靠虚拟存储器实现,延迟绑定的核心在于两张表:PLT(Procedure Linkage Table)和GOT(Global Offset Table)。基于虚拟存储器的代码共享使得在内存中只存在某个模块的唯一一份代码,通过虚拟存储器的内存映射机制将物理地址空间中的代码映射到不同进程的虚拟地址空间中(如下图)。

虚拟存储器

编译的时候不直接拷贝可执行代码,而是通过记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统,操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享内存中找到可执行代码,最终达到运行时连接的目的

它的缺点:运行时加载,可能会影响前期性能

上一篇下一篇

猜你喜欢

热点阅读