DLL和LIB文件-什么以及为什么?


Answers:


298

有静态库(LIB)和动态库(DLL)-但请注意,.LIB文件可以是静态库(包含目标文件)或导入库(包含允许链接程序链接到DLL的符号)。

使用库是因为您可能有要在许多程序中使用的代码。例如,如果您编写一个计算字符串中字符数的函数,则该函数在许多程序中将很有用。一旦该函数正常工作,您就不必每次使用时都重新编译代码,因此您可以将该函数的可执行代码放入库中,链接器可以提取已编译的代码并将其插入到程序中。因此,静态库有时也称为“归档”。

动态库使这一步骤更进一步。在每个程序中占用多个库函数副本似乎很浪费。他们为什么不能全部共享一个功能副本?这就是动态库的用途。与其在编译时将库代码构建到程序中,不如将其加载到内存中时通过将其映射到您的程序中来运行它。使用相同功能同时运行的多个程序可以共享一个副本,从而节省内存。实际上,您只能根据需要加载动态库,具体取决于代码的路径。如果您不进行任何打印,则让打印机例程占用内存没有任何意义。另一方面,这意味着您必须在运行程序的每台计算机上安装动态库的副本。

例如,几乎所有用“ C”编写的程序都需要来自称为“ C运行时库”的库中的功能,尽管很少有程序需要所有功能。C运行时提供静态版本和动态版本,因此您可以根据特定需要确定程序使用哪个版本。


80
事实证明,.LIB文件可以是静态库(包含目标文件),也可以是导入库(包含允许链接器链接到DLL的符号)。我想知道为什么会这样。
Lumi

2
很好的解释!在使用Dll的应用程序之间共享代码,并且(默认情况下)不共享数据。
mox

4
@Lumi:好点。在DLL方面,我们有两种类型的链接。隐式链接,当我们有.libDLL创建者提供的文件以及相应的标头时;这.lib只是目标DLL的描述符,它包含地址,入口点等,但没有代码。这.lib必须传递给链接器。第二个是当我们通过使用函数手动加载DLL时显式链接LoadLibrary。在这种类型中,我们不需要该.lib文件,但是我们必须花点力气找到DLL导出,它们的地址,并通过指针调用这些函数。
itachi

37

另一个方面是安全性(混淆)。一旦从主应用程序中提取了一段代码并将其放入“分离的”动态链接库中,由于代码已被隔离,因此更易于攻击,分析(反向工程)代码。当同一段代码保存在LIB库中时,它就是已编译(链接)目标应用程序的一部分,因此,这很难将该代码段与其余目标二进制文件隔离(区分)。


安全方面对我来说是新的。在C#应用程序调用本机非托管C ++ dll的情况下,上述推理是否成立?
马丁

1
但是LIB也是孤立的,不是吗?因此,攻击者可以简单地分析LIB。还是常见的情况是公众无法访问LIB?
Nick Russler 2014年

8
就编译器过程而言,LIB也是“隔离的”,但是一旦链接器将各个部分放在一起,LIB就是EXE的一部分,无法与您自己的代码区分开。
mox

17

创建DLL / LIB而不是仅将代码编译成可执行文件的一个重要原因是重用和重定位。例如,普通的Java或.NET应用程序很可能会使用多个第三方(或框架)库。只需要针对一个预先构建的库进行编译,就比将所有第3方代码都编译到您的应用程序中更加容易和快捷。将代码编译到库中还可以鼓励良好的设计习惯,例如,设计要在不同类型的应用程序中使用的类。


7

DLL是在其他可执行程序之间共享的功能库。只需查看Windows / system32目录,您就会发现其中的几十个。当您的程序创建DLL时,它通常还会创建一个lib文件,以便应用程序* .exe程序可以解析DLL中声明的符号。

.lib是静态链接到程序的函数库-它们不会与其他程序共享。与* .lib文件链接的每个程序都具有该文件中的所有代码。如果您有两个与C.lib链接的程序A.exe和B.exe,则每个A和B都将包含C.lib中的代码。

创建DLL和库的方式取决于您使用的编译器。每个编译器的处理方式都不同。


4

另一个不同之处在于性能。

由于DLL在运行时由.exe加载,因此.exe和DLL使用共享内存概念工作,因此相对于静态链接,性能较低。

另一方面,.lib是在编译时静态链接到所请求的每个进程的代码。因此,(exe)文件将具有单个内存,从而提高了进程的性能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.