⚙️ 第八章 从源文件到可执行文件
📄 一句话概括

DLL 让全系统共用同一份库代码(5 MB 的库,100 个程序从 500 MB 降到 5 MB);导入库不是库本身,只是指路牌。

📝 本节和前面几节的关系

8.5 提到了库文件,这一节把库的两种接法说清楚。

一、两种接法

静态链接:把用到的库代码直接复制进可执行文件。 动态链接:只记下【要用哪个库里的哪个函数】,运行时才去加载。 静态的好处是不依赖别人——拿到文件就能跑。 动态的好处是省地方——同一个库,全系统只留一份。

二、算一笔账

一个库 5 MB,100 个程序都要用它。 静态:磁盘上躺着 100 份,共 500 MB;内存里也是每个程序各占一份。 动态:磁盘上只有 5 MB,运行时多个程序共用同一份内存中的副本。 所以省下的不只是磁盘,更关键的是内存——这在内存只有几十兆的年代是决定性的。

三、导入库是什么

名字容易混:导入库不是库本身,它只是一张【指路牌】。 里面记着【你要用的那个函数,在哪个 DLL 里】。 编译时靠它确认名字拼得对;真正运行时才去把那个 DLL 加载进来。 所以真正干活的是 DLL,导入库只负责牵线。

四、动态链接的麻烦

好处换来的是三类新问题: 找不到文件——DLL 丢了或被删了,程序直接起不来。 版本冲突——好几个程序用同一个 DLL,但要求不同的版本。 连带故障——一个 DLL 出问题,所有依赖它的程序一起倒下。 这三条你大概都见过:系统里那些红色的缺失文件提示,说的就是它们。

五、动手 Demo:DLL文件与导入库

程序要用的库,有两种接法:静态链接和动态链接。 算一笔账就明白 DLL 为什么存在。

lib_mb = 5
progs = 100
print("静态链接  磁盘占用 %d MB" % (lib_mb * progs))
print("动态链接  磁盘占用 %d MB" % lib_mb)
print("省下      %d MB" % (lib_mb * progs - lib_mb))

实跑输出:

--------------------------------------------------------------------
DLL文件与导入库
--------------------------------------------------------------------

程序要用的库,有两种接法:

  对比项       静态链接                   动态链接(DLL)
  -----------------------------------------------------------
  磁盘占用     每个程序各存一份库代码     全系统只存一份
  内存占用     每个程序各占一份           多个程序共用同一份
  升级库       所有程序都要重新链接       换掉那个文件就行
  启动速度     快,不用去找               略慢,要去找并加载
  出问题       互不影响                   一个坏,全都受影响

  算一笔账:**一个库 5 MB,100 个程序都要用它。**

    静态链接    100 × 5 MB = 500 MB(磁盘上躺着 100 份)
    动态链接    5 MB          (只留一份,大家共用)
    省下        495 MB

  **这就是 DLL 存在的理由:省磁盘、更省内存。**

  那【导入库】又是干什么的?
  **它不是库本身,只是一张指路牌。** 里面记着【要用到的函数在哪个 DLL 里】。
  编译时靠它确认名字拼得对,**真正运行时才去把那个 DLL 加载进来。**
  **所以真正干活的是 DLL,导入库只负责牵线。**

一个 5 MB 的库被 100 个程序使用:静态要 500 MB,动态只要 5 MB,省下 495 MB。 省磁盘更省内存——运行时多个程序共用同一份库代码。

30 秒实验

  1. 在你电脑上搜一下 .dll 文件,看看有多少个、总共占多大。
  2. 想一想:为什么【卸载某个程序后另一个程序坏了】这种事会发生。

常见误区

  1. 以为 DLL 就是【一个库文件】。它真正的价值是让多个程序共用一份。
  2. 以为导入库里有函数代码。它只是指路牌,代码在 DLL 里。
自测三问(点开对答案) 1. 静态链接和动态链接的区别是什么? —— 静态把库代码复制进可执行文件;动态只在运行时去加载共享的库。 2. DLL 主要省的是哪一部分资源? —— 磁盘和内存——全系统共用同一份库代码,多个程序共用内存中的副本。 3. 导入库的作用是什么? —— 记录用到的函数在哪个 DLL 里,编译时用来核对,本身不含函数代码。

相关笔记