据我了解(如果我错了,请纠正我,我会在之后编辑我的帖子),在构建应用程序时,有两种使用库的方式:
1. 静态库(.a文件):在链接时,整个库的副本被放入最终的应用程序中,以便库中的函数始终对调用应用程序可用。 2. 共享对象(.so文件):在链接时,对象只是通过相应的头文件(.h文件)对其API进行验证。直到运行时需要时,库才会被实际使用。
静态库的明显优势是它们使整个应用程序成为自包含的,而动态库的好处是“.so”文件可以被替换(例如:如果由于安全漏洞需要更新),而无需重新编译基本应用程序。
我听说有些人在共享对象和动态链接库(DLL)之间做了区分,尽管它们都是“.so”文件。在Linux或其他POSIX兼容的操作系统(如MINIX、UNIX、QNX等)上进行C/C++开发时,共享对象和DLL之间是否有区别?据我所知,一个关键的区别(至少目前是这样)是共享对象仅在运行时使用,而DLL必须首先在应用程序中使用dlopen()函数进行打开。
最后,我还听说一些开发人员提到了“共享归档”,据我理解,它们本身也是静态库,但不会直接被应用程序使用。相反,其他静态库将链接到“共享归档”,从中提取一些(但不是全部)函数/资源到正在构建的静态库中。
更新
在这些术语被提供给我的背景下,这实际上是一组Windows开发人员在学习Linux时使用的错误术语。我试图纠正他们,但是(错误的)语言规范仍然被坚持使用。
共享对象:在程序启动时自动链接到程序中的库,作为一个独立的文件存在。该库在编译时包含在链接列表中(例如:对于名为mylib.so的库文件,LDOPTS+=-lmylib)。该库必须在编译时和应用程序启动时存在。 静态库:在构建时将库合并到实际程序本身中,用于包含应用程序代码和自动链接到程序的库代码的单个(较大)应用程序。最终的二进制文件包含主程序和库本身,作为一个独立的二进制文件存在。该库在编译时包含在链接列表中(例如:对于名为mylib.a的库文件,LDOPTS+=-lmylib)。该库必须在编译时存在。 DLL:与共享对象基本相同,但不是在编译时包含在链接列表中,而是通过dlopen()/dlsym()命令加载库,以便程序在编译时不需要该库。此外,该库不需要在应用程序启动或编译时存在,因为它只在dlopen/dlsym调用时需要。 共享存档:与静态库基本相同,但使用了“export-shared”和“-fPIC”标志进行编译。该库在编译时包含在链接列表中(例如:对于名为mylibS.a的库文件,LDOPTS+=-lmylibS)。两者之间的区别在于,如果共享对象或DLL希望将共享存档静态链接到自己的代码中,并能够使共享对象中的函数对其他程序可用,而不仅仅在DLL内部使用它们,则需要此附加标志。当有人向您提供一个静态库,并且您希望将其重新打包为SO时,这非常有用。该库必须在编译时存在。
额外更新
在我当时工作的公司中,“DLL
”和“共享库
”之间的区别只是一种(懒散、不准确的)口头说法(当时的Windows开发人员被迫转向Linux开发,这个术语就流传开来),遵循上述所述的描述。
此外,在“共享存档”中,库名称后面的“S
”字面量只是该公司使用的一种约定,并不普遍存在于整个行业中。
.a
文件,"a" 实际上代表 "archive"(归档文件),它只是一组目标文件的归档。现代链接器应该足够智能,不需要包含整个库,只需包含所需的归档中的目标文件,并且可能仅使用引用的目标文件中的代码/数据部分。 - Some programmer dude