C++ 共享对象(.so)、静态库(.a)和DLL';是吗?

C++ 共享对象(.so)、静态库(.a)和DLL';是吗?,c++,c,linux,dll,linker,C++,C,Linux,Dll,Linker,我参与了一些关于Linux库的辩论,我想确认一些事情 根据我的理解(如果我错了,请纠正我,稍后我将编辑我的文章),在构建应用程序时有两种使用库的方法: 静态库(.a文件):在链接时,将整个库的副本放入最终应用程序中,以便调用应用程序始终可以使用库中的函数 共享对象(.so文件):在链接时,通过相应的头(.h)文件根据其API验证对象。该库直到运行时才被实际使用,在运行时需要它 静态库的明显优点是,它们允许整个应用程序是自包含的,而动态库的好处是可以替换“.so”文件(即:如果由于安全缺陷需要更新

我参与了一些关于Linux库的辩论,我想确认一些事情

根据我的理解(如果我错了,请纠正我,稍后我将编辑我的文章),在构建应用程序时有两种使用库的方法:

  • 静态库(.a文件):在链接时,将整个库的副本放入最终应用程序中,以便调用应用程序始终可以使用库中的函数
  • 共享对象(.so文件):在链接时,通过相应的头(.h)文件根据其API验证对象。该库直到运行时才被实际使用,在运行时需要它
  • 静态库的明显优点是,它们允许整个应用程序是自包含的,而动态库的好处是可以替换“.so”文件(即:如果由于安全缺陷需要更新),而无需重新编译基础应用程序

    我听说有些人区分了共享对象和动态链接库(DLL),尽管它们都是“.so”文件。在Linux或任何其他兼容POSIX的操作系统(如MINIX、UNIX、QNX等)上进行C/C++开发时,共享对象和DLL之间有什么区别吗?我被告知一个关键的区别(到目前为止)是共享对象只在运行时使用,而DLL必须首先在应用程序中使用dlopen()调用打开

    最后,我还听到一些开发人员提到“共享档案”,据我所知,它们本身也是静态库,但从未被应用程序直接使用。相反,其他静态库将与“共享归档”链接,以将共享归档中的一些(但不是全部)功能/资源拉入正在构建的静态库中

    提前感谢大家的帮助

    更新
    在向我提供这些术语的上下文中,必须学习Linux的Windows开发团队使用的术语实际上是错误的。我试图纠正它们,但(不正确的)语言规范仍然存在。

  • 共享对象:程序启动时自动链接到程序中的库,作为独立文件存在。该库在编译时包含在链接列表中(即:对于名为
    mylib.so
    的库文件,
    LDOPTS+=-lmylib
    库必须在编译时以及应用程序启动时存在。
  • 静态库:单个(较大)应用程序在构建时合并到实际程序中的库,其中包含应用程序代码和库代码,在构建程序时自动链接到程序中,最后一个包含主程序和库本身的二进制文件作为一个独立的二进制文件存在。该库在编译时包含在链接列表中(即:对于名为mylib.a的库文件,
    LDOPTS+=-lmylib
    库必须在编译时存在。
  • DLL:基本上与共享对象相同,但不是在编译时包含在链接列表中,而是通过
    dlopen()
    /
    dlsym()
    命令加载库,以便在编译程序时不需要出现库此外,该库不需要(必须)在应用程序启动或编译时出现,因为它只需要在调用
    dlopen
    /
    dlsym
    时出现
  • 共享存档:本质上与静态库相同,但使用“导出共享”和“-fPIC”标志编译。该库在编译时包含在链接列表中(即:对于名为
    mylibS.a
    的库文件,
    LDOPTS+=-lmylibS
    )。两者之间的区别在于,如果共享对象或DLL希望将共享存档静态链接到其自己的代码中,并且能够使共享对象中的函数可供其他程序使用,而不仅仅是在DLL内部使用,则需要此附加标志。当有人向您提供静态库,并且您希望将其重新打包为SO时,这非常有用库必须在编译时存在。
  • 补充更新 “
    DLL
    ”和“
    shared library
    ”之间的区别只是我当时所在公司的一种(懒惰、不准确的)俗语(Windows开发人员被迫转向Linux开发,术语卡住了),遵守了上述描述


    此外,在“共享存档”的情况下,库名称后面的“
    S
    ”文字只是该公司使用的一种惯例,而不是在整个行业中使用。

    我一直认为DLL和共享对象只是同一事物的不同术语-Windows称它们为DLL,在UNIX系统上,它们是共享对象,通用术语-动态链接库-涵盖了这两个对象(甚至包括打开.com.cn的函数),因此在UNIX上,在“动态库”之后称为
    dlopen()

    它们确实只在应用程序启动时链接,但是您对头文件进行验证的概念是不正确的。头文件定义了编译使用库的代码所需的原型,但在链接时链接器会查看库本身,以确保它所需的函数实际存在。链接器必须在链接时的某个地方找到函数体,否则会引发错误。它在运行时也会这样做,因为正如您正确指出的那样,自编译程序以来,库本身可能已经发生了更改。这就是ABI稳定性在平台库中如此重要的原因,因为ABI的变化打破了针对旧版本编译的现有程序