为什么我们在编译期间需要共享库

why do we need the shared library during compile time

为什么在我的可执行文件的编译期间需要共享库存在?我的理由是,由于共享库未包含在我的可执行文件中并在运行时加载,因此在编译时不应该需要它。还是我遗漏了什么?

#include<stdio.h>
int addNumbers(int, int); //prototype should be enough, no? 
int main(int argc, char* argv[]){
  int sum = addNumbers(1,2);
  printf("sum is %d\n", sum);
  return 0;
}

我的当前目录中有 libfoo.so,但我将其名称更改为 libfar.so,发现编译时需要共享库,否则无法编译。

gcc -o main main.c -L. -lfoo 给出 main.c:(.text+0x28): undefiend reference to 'addNumber'

我觉得只要有共享库的名字就够了。不需要共享库本身,因为它在 LD_LIBRARY_PATH 中找到并在运行时动态加载。除了共享库的名称,还需要其他什么吗?

gcc -o main main.c -L. -lfoo

此命令执行(至少)两个步骤:将 main.c 编译成一个目标文件,link 将所有资源编译成可执行文件 main。您看到的错误来自最后一步,link呃。

linker 负责生成最终的可执行机器代码。它需要共享对象库,因为它需要生成加载它并执行其中使用的任何函数的机器代码。

编译 时不需要任何东西,因为 C 有单独编译 翻译单元 的概念。但是,一旦编译了所有不同的来源,就该 link 将所有内容放在一起了。标准中没有共享库的概念,但它现在已经很常见了,所以这里是 common linker 的处理方式:

  • 它在所有已编译的模块中查找具有外部 linkage 定义或仅声明的标识符
  • 它在库(静态和动态)中查找已使用但未定义的标识符。然后它 links 来自静态库的模块,并存储来自动态库的引用。但至少在 Unix-likes 上,它需要访问共享库以获取可能需要的(声明的和未定义的)标识符,以确保它们已经定义或可以在其他 linked 库中找到它们是静态的或动态

这将生成可执行文件。然后在加载时,动态加载器知道所有需要的动态模块并将它们与实际的可执行文件一起加载到内存中(如果它们还不存在)并构建一个(虚拟)内存映射