与动态情况相比,关于静态库和链接,有三个主要问题需要谨记:
静态库更加自主,但适应能力较差。
如果以静态方式绑定 a.out 可执行文件,它所需的库例程会变成可执行二进制文件的一部分。但是,如果需要更新绑定到 a.out 可执行文件中的静态库例程,则必须重新链接并重新生成整个 a.out 文件以便利用已更新的库。对于动态库,库并不是 a.out 文件的一部分,并且链接是在运行时完成的。要利用已更新的动态库,只需将新库安装在系统中即可。
静态库中的“元素”是单独的编译单元,即 .o 文件。
由于单个编译单元(源文件)可以包含多个子程序,因此这些例程在一起编译时会变成静态库中的单一模块。这就意味着会将编译单元中的所有例程一起装入 a.out 可执行文件中,即使实际只调用了那些子程序中的一个。通过优化库例程分发到可编译源文件中的方式,可以改善这种情况。(尽管如此,只有程序实际引用的那些库模块才会被装入可执行文件。)
链接静态库时,顺序很重要。
链接程序按输入文件在命令行上出现的顺序(从左至右)对其进行处理。当链接程序决定是否从库中加载某一元素时,其决定取决于它已经处理的库元素。该顺序不仅依赖于元素在库文件中的出现顺序,而且还依赖于编译命令行中指定库的顺序。
示例:如果 Fortran 程序在两个文件(main.f 和 crunch.f)中,并且只有后者访问某个库,则在 crunch.f 或 crunch.o 之前引用该库是错误的:
demo% f95 main.f -lmylibrary crunch.f -o myprog |
(不正确)
demo% f95 main.f crunch.f -lmylibrary -o myprog |
(正确)