Luke Davis Asked: 2018-02-19 11:40:55 +0800 CST2018-02-19 11:40:55 +0800 CST 2018-02-19 11:40:55 +0800 CST 为什么我必须在运行程序之前设置 LD_LIBRARY_PATH,即使我已经在编译阶段链接了库位置?[复制] 772 我正在使用make. 该模型有一个Makefile通过看起来像的标志将源代码与依赖库连接起来-L/lib1 -L/lib2。但是当我尝试运行该模型时,它会失败,除非我也确保环境变量 export LD_LIBRARY_PATH=/lib1:/lib2 并指向完全相同的库。这对我来说似乎是多余的。 这里的引擎盖下可能发生了什么?为什么我必须在编译之前和执行之前有效地指定库的位置? 这可能是一个愚蠢的问题;我对编译机器代码不是很有经验,通常只使用脚本语言。 compiling libraries 1 个回答 Voted Best Answer Matthew Gauthier 2018-02-19T23:45:30+08:002018-02-19T23:45:30+08:00 尽管每个人都在将源代码转换为可执行文件的通俗意义上使用编译,但从技术上讲,这是一个相当长的管道中的一个步骤: 输入文件通过预处理器运行,生成单个翻译单元。 预处理器的输出被编译成汇编。 汇编器将其作为输入并输出一个目标文件。 链接器将目标文件拼接在一起以生成可执行文件。 [为了迂腐,没有要求这些步骤是分开的,现代编译器通常将它们组合起来以提高效率。] 我们关心的是链接步骤,它将您的代码与标准系统库结合起来。链接器将静态库中的对象直接复制到可执行文件中。但是,对于共享库,它只提供对该库的引用。 共享库有很多优点。您可以在不重新编译程序的情况下更新它们,并且它们使用更少的内存,因为程序可以共享公共代码。它们还有一个明显的缺点,即代码不在可执行文件中。 解决方案是动态加载器,它负责在运行时解析所有共享库引用。加载器自动运行;这样做的指令是链接器包含在可执行文件中的一件事。当然,这以加载器可以找到库为前提。 系统库位于标准目录中,这很简单。如果不是这种情况,加载程序将搜索 LD_LIBRARY_PATH。为什么链接器不只是将路径放在可执行文件中?因为那样您将无法移动或更改库。 实际上,您也无法真正移动可执行文件,因为该库位于系统搜索路径之外。如果它仅在库位于 ~luke/lib 中时运行,那么除非他可以读取您的文件,否则您不能将其交给 joe。如果你换一份新工作,乔会很糟糕。 仅供参考,它也会以无数其他方式吸收。如果您只能在编译时指定库位置,除其他外,调试将成为永恒的噩梦。
尽管每个人都在将源代码转换为可执行文件的通俗意义上使用编译,但从技术上讲,这是一个相当长的管道中的一个步骤:
[为了迂腐,没有要求这些步骤是分开的,现代编译器通常将它们组合起来以提高效率。]
我们关心的是链接步骤,它将您的代码与标准系统库结合起来。链接器将静态库中的对象直接复制到可执行文件中。但是,对于共享库,它只提供对该库的引用。
共享库有很多优点。您可以在不重新编译程序的情况下更新它们,并且它们使用更少的内存,因为程序可以共享公共代码。它们还有一个明显的缺点,即代码不在可执行文件中。
解决方案是动态加载器,它负责在运行时解析所有共享库引用。加载器自动运行;这样做的指令是链接器包含在可执行文件中的一件事。当然,这以加载器可以找到库为前提。
系统库位于标准目录中,这很简单。如果不是这种情况,加载程序将搜索 LD_LIBRARY_PATH。为什么链接器不只是将路径放在可执行文件中?因为那样您将无法移动或更改库。
实际上,您也无法真正移动可执行文件,因为该库位于系统搜索路径之外。如果它仅在库位于 ~luke/lib 中时运行,那么除非他可以读取您的文件,否则您不能将其交给 joe。如果你换一份新工作,乔会很糟糕。
仅供参考,它也会以无数其他方式吸收。如果您只能在编译时指定库位置,除其他外,调试将成为永恒的噩梦。