0

我对与位置无关的代码及其在动态库中的使用感到非常困惑。

我发现了这个关于 GCC 的 -fPIC 选项的好例子:GCC -fPIC 选项 ,我弄清楚了它是如何工作的。

但是,我很难理解为什么动态库需要独立于特定地址的代码。加载动态库时,为什么我们不能只保存其绝对地址(例如库中函数的地址)并使用它们?为什么在这种情况下必须使用相对地址?

用“gcc main.c”编译的简单程序int main() { return 0; }总是依赖于位置?

4

1 回答 1

2

-fPIC绝不是共享库问题的唯一解决方案。在 ELF Linux 之前使用a.out 可执行格式。在a.out所有共享库中,都在全局地址空间中使用了唯一地址,因此它们总是被所有进程加载到相同的固定地址。事实证明,这非常难以管理:所有发行版包必须在彼此之间达成一致,为哪个库保留哪个地址范围,并且随着库随着时间的推移不断修改该协议。

-fPIC让我们摆脱了这个混乱。

根据您的建议,所有进程的地址范围的全局动态保留,一旦某个进程在某个内存区域映射了一个库,即使它从未实际加载该库,其他进程也无法重用该区域。对于具有 4G 地址空间的 32 位系统(甚至 2G 是为内核保留的上层 2G),这可能会很快耗尽 VM。另一个问题来自这样一个事实,即主可执行文件的大小因进程而异,因此没有可以安全加载库的全局起始地址。

于 2021-06-17T05:05:38.180 回答