假设我有fowling C代码,我正在使用gcc在linux机器上编译它。
test.c的:
int main(){ 的printf( “喜\ n”); 返回0;}我知道stdio.h定义了……
在进行正常编译时 gcc test.c ,链接器是否建立动态链接 printf 还是静态链接? 醇>
gcc test.c
printf
这取决于。鉴于特定的编译命令,如果C库的动态版本可用,并且如果构建GCC以使用它(两者都很有可能),那么GCC将执行动态链接。如果只有C库的静态版本可用,或者默认情况下构建或配置GCC静态链接,则将执行静态链接。
printf 最终成为一个 write() 系统调用。链接器是否复制了定义的C lib printf 到最后的可执行文件(哪个 最终会打电话 write() 在运行时)或是复制 write() 直接在最后的可执行文件中。 醇>
write()
如果GCC正在执行静态链接,那么它将直接或间接地将程序所需的所有函数(以及其他函数)复制到最终二进制文件中。我特别不确定GNU链接器,但是一些链接器将在最终二进制文件中包含整个目标库。
如果我编译我的代码然后卸载C lib我的代码仍会运行?以来 printf 在任何地方都没有定义。 醇>
如果您将C库静态链接到程序中,那么之后删除C库将不会(直接)阻止程序运行。但根据细节,它可能会阻止 其他一切 从运行,包括GUI,您的其他应用程序,甚至shell,从而提出问题。
静态链接 所有 必需的库是一种合理的技术,可以最大限度地减少二进制文件的运行时依赖性,从而提高与不同于构建环境的系统的兼容性。这往往会产生 许多 但是,更大的二进制文件。在任何情况下,除非您以这种方式构建每个程序,否则在事实之后删除库通常不是可行的替代方案。
首先,一些背景。在Unix系统上(我所知道的)C运行时包含标准C函数实现和所谓的 胶 代码(从C程序调用低级OS函数所需)。
在你的例子中, printf() 是一个C运行时函数,和 write() 是一个 胶 接口 write 系统调用。假设我们正在谈论linux,它们都将存在于glibc库中。
printf()
write
当您链接程序时,默认情况下gcc链接器将首先尝试动态链接到glibc(使用.so)。这可以通过对链接器使用-static参数来改变 - 它将强制glibc的静态链接,更多信息可以在这里找到: Glibc的静态链接
您可以通过签发来检查最终结果 ldd <path to your executable> - 这将显示链接器请求的所有.so库。
ldd <path to your executable>