当前位置: 首页 > 知识库问答 >
问题:

如何将标准库静态链接到我的c程序?

屈健柏
2023-03-14

我正在将Code::Blocks IDE(v13.12)与GNU GCC编译器一起使用。

  1. 我想使用链接器链接我的程序所需的运行库的静态版本,我可以怎么做
  2. 我已经知道我的可执行文件的大小会增加,你能告诉我其他的缺点吗
  3. 在Visual C Express中执行此操作怎么样

共有2个答案

阴高寒
2023-03-14

在Visual C中, /MT选项执行静态链接, /MD选项执行动态链接。

我建议使用 /MD并重新分发C运行时,这可以从Microsoft免费获得。一旦C运行时被安装,比任何需要运行时间的程序都将继续工作。您需要传递正确的选项来告诉编译器要使用哪个运行时。这里有一个很好的解释,我应该用 /MD还是 /MT编译?

在Linux上,我建议重新分发libstdc而不是静态链接。如果他们的系统libstdc工作,我会让用户直接使用它。系统库,如libpthread和libgcc,应该只使用系统默认值。这需要在一个系统上编译程序,该系统的符号与您正在分发的所有linux版本兼容。

在Mac OS X上,只需重新发布应用程序,并动态链接到libstdc即可。任何使用相同操作系统版本的人都应该能够使用您的程序。

党建义
2023-03-14

既然还没有人想出答案,我就试试看。不幸的是,我不知道Code::阻塞了IDE,所以我的答案只能是部分的。

这不是特定于IDE的,但一般适用于GCC(和许多其他编译器)。假设您在main.cpp中有一个简单的“Hello, world”程序(除了标准库和运行库之外,没有外部依赖)。您可以通过以下方式编译并静态链接它:

>

  • 编译main。cppmain。o(输出文件名为隐式):

    $ g++ -c -Wall main.cpp
    

    -c告诉GCC在编译步骤后停止(不运行链接器)。-Wall打开大多数诊断信息。如果新手程序员能够更频繁地使用它并更加关注它,那么这个网站上的许多问题就不会被问到

    链接main。o(可以列出多个目标文件)静态地拉入标准和运行时库,并将可执行文件放入文件main

    $ g++ -o main main.o -static
    

    如果不使用-o main开关,GCC会将最终可执行文件放在名称不太好的文件a.out(它曾经最终代表“程序集输出”)中。

    尤其是在开始的时候,我强烈建议“手工”做这样的事情,因为这将有助于更好地理解构建工具链。

    事实上,上述两个命令可以合并为一个命令:

    $ g++ -Wall -o main main.cpp -static
    

    任何合理的IDE都应该有指定此类编译器/链接器标志的选项。

    静态链接的原因:

    >

    您可以在共享库不可用的环境中执行该程序。例如,将静态链接的CGI可执行文件放入chroot()jail可能有助于减少web服务器上的攻击面。

    由于不需要动态链接,程序启动可能会更快。(我敢肯定,在某些情况下,情况正好相反,尤其是共享库已经为另一个进程加载的情况下。)

    由于链接器可以硬编码函数地址,函数调用可能更快。

    在安装了多个版本的公共库(例如LAPACK)的系统上,静态链接有助于确保始终使用特定版本,而无需担心如何正确设置LD\u library\u路径。显然,这也是一个缺点,因为现在您无法在不重新编译的情况下再选择库。如果您总是想要相同的版本,那么为什么一开始就要安装多个呢?

    反对静态链接的原因:

    >

  • 正如您已经提到的,可执行文件的大小可能会急剧增长。当然,这在很大程度上取决于您所链接的库。

    如果多个进程同时需要共享库,操作系统可能足够智能,只需将共享库的文本部分加载到RAM中一次。通过静态链接,您将失去这一优势,系统可能会更快地耗尽内存。

    您的程序不再从库升级中获利。系统管理员将不得不重新编译和重新安装使用它的每个程序,而不是简单地用一个(希望ABI兼容的)新版本替换一个共享库。这是我认为最严重的缺点。

    例如,考虑OpenSSL库。今年早些时候,当Heartbleed漏洞被发现并修复时,系统管理员可以安装修补版本的OpenSSL,并在修补程序发布后的一天内重新启动所有服务以修复该漏洞。也就是说,如果他们的服务是针对OpenSSL动态链接的。对于那些静态链接的软件,修复最后一个需要几周的时间,我很确定,到目前为止,仍然有一些专有的“一体式”软件尚未修复。

    用户无法动态替换共享库。例如,torock脚本(和相关库)允许用户将网络系统库替换为通过Tor网络路由其流量的库(通过适当地设置LD_PRELOAD)。这甚至适用于开发人员从未考虑过这种可能性的程序。(这是否安全和一个好主意是一个不相关的辩论主题。另一个常见的用例是通过用专门的版本替换malloc等来调试或“强化”应用程序。

    在我看来,除了非常特殊的情况外,静态链接的缺点在所有情况下都大于优点。根据经验:如果可以,动态链接;如果必须,静态链接。

    正如Alf所指出的(参见注释),有一个特殊的GCC选项可以选择静态链接C标准库,但不能静态链接整个程序。从GCC手册:

    -stest-libstdc

    当g程序用于链接C程序时,它通常会自动链接到libstdc。如果libstdc可作为共享库使用,并且未使用-ista选项,则会链接到libstdc的共享版本。这通常没问题。然而,有时冻结程序使用的libstdc版本是有用的,而不会一直到完全静态的链接。-stest-libstdc选项指示g驱动程序静态链接libstdc,而不必静态链接其他库。

  •  类似资料:
    • 问题内容: 我试图将静态库(与gcc一起编译)链接到C 程序,但出现了“未定义引用”。我在ubuntu 12.04服务器计算机上使用了gcc和g 版本4.6.3。例如,这是阶乘方法的简单库文件: mylib.h mylib.c 我使用gcc为此mylib.c创建了对象: 再次使用AR实用工具从目标文件创建了静态库: 我用C程序(test.c)和C ++程序(test.cpp)测试了这个库 C和C

    • 问题内容: 在Linux上的“ C”上, 我需要静态库来静态链接,还是需要足够的共享库?如果没有,为什么不呢?(它们不包含相同的数据吗?) 问题答案: 是的,您需要静态库来构建静态链接的可执行文件。 静态库是编译对象的捆绑包。静态链接到库时,实际上与获取该库的编译结果,将它们解压缩到当前项目中以及将它们当作自己的对象使用一样。 动态库已链接。这意味着一些信息,例如重定位,已经被修复并丢弃。 此外,

    • 问题内容: Java 8之前的Java版本要求本机代码必须位于共享库中,但是我已经读到Java 8可以在JNI中使用静态链接库。我已经搜索了示例,但找不到任何示例。 如何将JNI库静态链接到Java应用程序? 问题答案: Java SE 8规范已更改为支持静态链接,并且静态链接在JDK中实现。在System.loadLibrary的规范中对此进行了简要介绍。它所引用的JNI规范的各个部分在此处和此

    • 问题内容: 我需要在ubuntu机器上编写的软件中使用libcurl。我正在使用Eclipse编写和编译所有软件。当我将libcurl文件与.cpp文件放在同一文件夹中,并在头文件中包含curl.h文件时,当我尝试编译程序时,出现以下错误: 我从libcurl中获取了include文件夹的内容,并将其与.cpp文件放在同一文件夹中。然后在.cpp文件的标题中,键入: 我也尝试过: 关于这个问题有什

    • 问题内容: 在Linux中,下载了程序源并希望将其静态链接。我那里有一个巨大的Makefile 编译。预言这有点太笼统了,但是如何使二进制文件静态链接? 编辑:这样做的原因是要确保二进制文件没有依赖性(或至少尽可能少),从而使其可以在任何基于Linux的计算机上运行,​​甚至可以在没有Internet连接和未更新的Linux上运行。 问题答案: 大多数生成的脚本将允许您进行静态构建: 如果这样不起

    • 问题内容: 我正在尝试使用在Linux上运行的CMake构建基于OpenCV的项目。到目前为止,我的文件看起来像 但这会导致动态链接的库。如何链接静态库? 问题答案: 您可以通过在CMake 中将标志设置为false来构建静态OpenCV库。然后,使用这些静态库构建自己的应用程序所需要做的就是在您的计算机中添加对OpenCV的依赖: 和CMake将照顾一切。