

在这篇博客文章中,我将讨论静态库和动态库,并探讨以下内容:为什么要使用库,它们如何工作,如何在Linux机器上创建这些库,如何在代码中利用它们,将两者作比较和对比。并从整体上探讨这两种图书馆的弊端。
免责声明:在阅读之前,请记住,这是一个博客文章,主要是根据我自己的在线研究和个人经验创建的。 我是学生,因此绝不是该主题的专家。 话虽如此,我希望您发现该内容是一种令人愉快的有用资源,并且它提供了一种替代方法,可以从学生的角度更容易理解。
本质上说,库只是存在于您机器中特定文件夹中的已编译代码的集合(稍后我们将对此进行扩展)。 这些库在链接阶段的编译过程中添加到您的代码中。 库是很棒的工具,因为它们允许您重用以前由另一个程序员或您自己编写的代码。 您可以在这些库中使用函数,而不必担心编译,甚至不必担心内部代码如何工作。 反过来,这将使您可以专注于手头的问题,而不必担心所述功能的实现细节。 例如,假设您正在编写一个程序,其中需要计算数字的长度。 您可以编写一个可以提供此答案的函数,但是如果已经有一个包含该函数的库,您要做的就是将其导入并使用,而不是从头开始。 简单,快速,简单。
如前所述,库是在链接阶段的编译过程中添加到您的代码中的。 这是准确的,但是正是在这里,添加代码的方式在很大程度上将静态库与动态库区分开。
对于静态库,链接阶段将库的实际二进制文件添加到打算使用该库的代码的二进制文件中。 这是静态库的主要缺点。 使用的库越多,可执行文件的大小将越大。 另一个缺陷是,如果库得到更新,则可执行文件将无法识别更改,因此您将需要重新编译代码才能应用任何新更新。 但是动态库有不同的方法。 链接器将仅在库所在的位置添加地址,从而修复大小和更新问题。 这比静态库需要将二进制代码添加到应用程序代码中的可执行文件要方便得多。
话虽这么说,如果动态库解决了很多问题,为什么静态库甚至存在? 考虑一下动态库是如何工作的; 请注意,获得对该库的更新意味着丢失计算机中预先建立的先前版本。 如果存在错误或您的代码与较新版本不兼容,这可能会导致一些严重的问题。 这被称为DLL-Hell(动态链接库地狱),但是通过赋予程序员版本库功能,它已在较新的OS版本上得到解决。 因此,在大多数情况下,动态库被认为是更好的方法。
准备好编译程序后,请执行以下操作:
将所有C文件编译成目标文件


您可以看到我使用了以下编译选项:
- -c :编译或汇编源文件,但不链接。
- – 墙 :包括所有警告。
- -Wextra :启用-Wall未启用的其他警告标志。
- -Werror :使所有警告变为错误。
- -pedantic :发出严格的ISO C和ISO C ++要求的所有警告。
有关更多详细信息,请参见gcc手册页。
现在使用ar程序来创建档案。


- r :将文件插入存档。
- c :为了创建存档。
- s :将目标文件索引写入存档或更新现有索引。
可选的:
使用ranlib来生成要存档的索引。 注意:请注意, ar与ranlib有何相同之处 ? 这是因为在存档上运行ar等效于运行ranlib 。


准备好编译代码后,请执行以下操作:
将所有C文件编译成目标文件
您可以看到我使用了以下编译选项:


- -fPIC :用于输出位置无关代码的编译器指令,这对于创建共享库是必需的。 另请参阅-fpic 。
- -c :编译或汇编源文件,但不链接。
- -Wall :包括所有警告。
- – Wextra :启用-Wall未启用的其他警告标志。
- -Werror :使所有警告变为错误。
- -pedantic :发出严格的ISO C和ISO C ++要求的所有警告。
有关更多详细信息,请参见gcc手册页。
然后使用“共享”标志来生成共享对象,然后可以将其与其他对象链接以形成可执行文件。


还记得我提到过某些目录中是否存在库吗? 创建动态库后,编译器需要知道在哪里可以找到该库。 您有多种选择; 首先是简单地将刚刚创建的动态库复制或移动到/ usr / lib或/ usr / local / lib文件夹中。 或者,如果您对此文件夹没有写权限,则可以将环境变量LD_LIBRARY_PATH设置为库所在的路径。 警告:注意不要删除LD_LIBRARY_PATH变量的当前值。
导出LD_LIBRARY_PATH =。:$ LD_LIBRARY_PATH
为了在代码中使用此库,只需在库中包含包含函数原型的标头,然后照常编译即可。
总结一下:
静态库
- 直接复制到可执行文件中。
- 库中发生更改时,可执行文件不会自动更新。
- 较大的可执行文件。
- 使用 ar和runlib命令。
- 具有前缀lib和扩展名.a。
动态图书馆
- 可执行文件中仅引用库的地址。
- 遇到库的新版本时,可执行文件将更新。
- 如果不使用版本控制,它将覆盖以前的库版本,可能会破坏您的可执行文件。
- 较小的可执行文件。
- 将gcc与-fPIC和-shared标志一起使用 。
- 具有前缀lib和扩展名.so 。