我想将我的程序分发为二进制文件,而不是源代码形式。我有两个测试系统:较旧的Linux(带有glibc 2.10的openSUSE 11.2)和最近的一个(带有glibc 2.15的LinuxMint 13)。现在当我使用glibc 2.15在LinuxMint系统上编译我的程序然后尝试使用glibc 2.10在openSUSE系统上启动二进制文件时,我得到以下两个错误:
./a.out: /lib/libc.so.6: version 'GLIBC_2.15' not found (required by ./a.out)
./a.out: /lib/libc.so.6: version 'GLIBC_2.11' not found (required by ./a.out)
这里让我感到困惑的是:为什么我这里也会收到“glibc 2.11 not found”错误?我希望程序现在需要glibc 2.15,因为它已经用glibc 2.15编译。为什么程序也在寻找glibc 2.11?这是否意味着我的程序将在两个glibc版本上运行,即2.15和2.11?所以它需要至少2.11?或者它在任何情况下都需要2.15?
另一个问题:假设glibc向上兼容但不向下是正确的吗?例如。是一个用glibc 2.10编译的程序,保证与glibc的任何未来版本完美配合?如果是这种情况,如果将来改变像PATH_MAX这样的常量会发生什么?目前设置为4096,我使用PATH_MAX常量为realpath()POSIX函数分配缓冲区。现在如果将来这个常量提高到8192,可能会出现问题,因为我的程序只分配了4096个字节。或者我在这里误解了什么?
感谢您的解释!
答案 0 :(得分:7)
Libc使用符号版本控制。它是相当高级的魔法,但基本上每个符号都根据它出现的版本附加标签。如果它的语义发生了变化,那么有两个版本,一个是旧语义,第一个出现的版本,另一个是新语义和出现的版本。加载器只会抱怨程序实际请求的符号。其中一些恰好在2.15中引入,其中一些恰好在2.11中引入。
这一点的重点是保持glibc向后兼容。这非常重要,因为有很多打包的软件,它们都是动态链接的,重新编译所有这些都需要很长时间。还有许多软件没有可用的源代码,旧的libc版本可能无法用于新内核或其他新内容。
所以是的,glibc是向后兼容的。只需确保您针对需要它运行的最旧版本进行编译,因为它不能(也不能)向前兼容。
Ad PATH_MAX:如果完成类似的更改,glibc将只导出使用新值的符号的新版本和具有适当安全值的旧版本符号,以使用针对旧值编译的代码。这是所有魔法的重点。