编译 – 为什么我必须在运行程序之前设置LD_LIBRARY_PATH,即使我已经在编译阶段链接了库位置?

参见英文答案 > Where do executables look for shared objects at runtime?                                    4个
我正在使用make编译模型;该模型有一个Makefile,它通过看起来像-L / lib1 -L / lib2的标志将源代码与依赖库连接起来.但是当我尝试运行该模型时,它会失败,除非我也确保环境变量

export LD_LIBRARY_PATH=/lib1:/lib2

并指向完全相同的库.这对我来说似乎是多余的.

引擎盖下有什么可以发生的?为什么我有效地必须在编译之前和执行之前指定库的位置?

这可能是一个愚蠢的问题;我不是很熟悉编译机器代码,通常只使用脚本语言.

解决方法:

尽管每个人都在将源代码转换为可执行文件的口语意义上使用编译,但从技术上讲,它只是在一个相当长的管道中的一个步骤:

>输入文件通过预处理器运行,从而生成单个翻译单元.
>预处理器的输出编译为汇编.
>汇编程序将输入作为输入输出目标文件.
>链接器将目标文件拼接在一起以生成可执行文件.

[要迂腐,不要求步骤分开,现代编译器通常将它们结合起来以提高效率. ]

我们关注的是链接步骤,它将您的代码与标准系统库相结合.链接器将对象从静态库直接复制到可执行文件中.但是,对于共享库,它仅提供对库的引用.

共享库有很多优点.您可以更新它们而无需重新编译程序,并且它们使用较少的内存,因为程序可以共享公共代码.它们也有明显的缺点,即代码不在可执行文件中.

解决方案是动态加载器,它负责在运行时解析所有共享库引用.装载机自动运行;这样做的说明是链接器在可执行文件中包含的一件事.当然这预示着加载器可以找到库.

系统库位于标准目录中,这很简单.如果不是这种情况,加载程序将搜索LD_LIBRARY_PATH.为什么链接器只是将路径放在可执行文件中?因为那时你将无法移动或更改库.

实际上,您也无法真正移动可执行文件,因为库位于系统搜索路径之外.如果它只在库位于~luke / lib时运行,那么除非他能读取你的文件,否则你不能将它交给joe.如果你搬到新工作岗位,那就很难过了.

仅供参考,它也会以无数其他方式吸收.如果你只能在编译时指定库位置,它会使调试成为永恒的噩梦.

上一篇:编译 – Pip安装 – 您选择的CPU不支持x86-64指令集


下一篇:shell-script – 什么是自动构建用于Unix和Windows构建C软件的32-64位库的最佳工具,可由用户和机器复制?