C语言的图书馆

杰出的图书馆链接

C语言中的对于提高效率非常有用。 C程序员经常发现自己一遍又一遍地编写相同的函数,例如复制字符串,查找字符串的长度等。这些函数最终变得如此普遍,以至于开发人员产生了库,常用函数的集合及其源代码。 库允许使用非常完善的有用功能,因为社区可以使用它们,并且如果发现错误,可以更新库。 确实会导致某些较长的大型库,但是节省时间是值得的。

在编译的最后一步,将库与汇编的机器代码链接。 因此,库本身作为机器代码存在,这意味着它们也需要进行编译。 它们通常可以是文件的集合,这些文件包含旨在包含在目标代码中的库中的功能。 目标代码和机器代码是等效的。 通过将库与已编译的可执行文件链接,某些功能无需调用开发人员即可编写被调用功能的功能。 GCC可以用来编译包含这些函数的c文件,然后gcc可以再次生成一个.so文件,代表共享库,换句话说就是一个动态库。

gcc -c -Wall -pedantic -Werror -Wextra -fpic ./*.c.c文件编译为带有位置无关代码标志的.o文件。

gcc -shared -o libname.so ./*.o生成动态库文件libname.so ,然后可以在编译过程gcc -shared -o libname.so ./*.o其链接为:

gcc -L. -Wall -pedantic -Werror -Wextra -lname ./*.c -o out

编译后,可执行文件只需要处于正确的环境中即可。 LD_LIBRARY_PATH是一个全局变量,它允许可执行文件在一系列目录中搜索并加载动态库。 要编辑LD_LIBRARY_PATH需要在bash中完成一些导出,可以在此处进行研究。 例如,您可能正在从包含库的文件夹中运行可执行文件,因此必须将当前目录添加到LD_LIBRARY_PATH

nm ldd ldconfig是用于开发和配置动态库的其他一些其他工具。 nm -D libname.so将提供库中包含的共享对象文件的列表。 这样可以确认正在开发中的动态库中是否包含所有必需的功能,并检查是否具有库文件。 ldd打印可执行文件的库依赖关系。 它将列出程序中包含的库以及在何处可以找到它们。 如果遇到not found ,则需要将相关库的路径添加到LD_LIBRARY_PATHldconfig通过生成将由其他程序访问的符号链接来在库位于另一个系统位置时对其进行缓存。

使用库可以通过上面的示例或我以前的文章中描述的静态库来完成。 库通常由已编译的可执行文件自动使用。 它们被“使用”的程度取决于链接的时间和位置。

上一篇文章中提到的静态库和动态库的目标基本相同。 实际上,它们的用法不同。 两种类型的库都为具有关键字功能的程序提供了外部编程的功能,而动态库则按需加载,而静态库则具有将所有必要信息插入可执行文件的功能。 当函数利用动态库时,动态库实际上已加载到内存中,而不是成为可执行文件内部的额外信息。 这是它们之间最大的区别。 动态库可以在可执行文件之间共享,而静态库仅影响它们链接到的可执行文件。 因此,动态库是在运行时完全加载的,因为动态加载器(将动态库数据移入内存的过程)不知道哪些功能是必需的。 但是,静态库是根据需要链接的,因此被调用的函数是链接的。

动态库改善了内存保护,因为它们仅对使用它们的所有程序加载一次。 不幸的是,这确实意味着必须将整个库加载到内存中。 静态库具有显式使用的函数链接到可执行文件,因此在使用较少的函数时会更好。 静态库的确会产生较大的可执行文件大小,因此动态库会导致文件大小减小。 可以更新动态库,并且不需要重新编译可执行文件,因为当没有其他程序使用可执行文件时,更新的动态库将与可执行文件一起动态加载。 静态库会导致重新编译,因为它们已链接到可执行文件,因此无论可执行文件被更新多少次,可执行文件都将保留该旧库。

动态和静态库的优缺点非常简单,因此在决定使用哪个库时,很大程度上取决于上下文和个人的偏好。