我如何将标准库静态链接到我的C ++程序? [英] How can i statically link standard library to my c++ program?

查看:88
本文介绍了我如何将标准库静态链接到我的C ++程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有GNU GCC编译器的Code :: Blocks IDE(v13.12).

I'm using Code::Blocks IDE(v13.12) with GNU GCC Compiler.

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

推荐答案

由于尚无人提出答案,因此我将尝试一下.不幸的是,我不知道Code :: Blocks IDE,所以我的回答只会是部分的.

Since nobody else has come up with an answer yet, I will give it a try. Unfortunately, I don't know that Code::Blocks IDE so my answer will only be partial.

这不是IDE特有的,但通常适用于GCC(和许多其他编译器).假设您在main.cpp中有一个简单的"hello,world"程序(除标准库和运行时库外,没有外部依赖项).您可以通过以下方式进行编译和静态链接:

This is not IDE specific but holds for GCC (and many other compilers) in general. Assume you have a simplistic "hello, world" program in main.cpp (no external dependencies except for the standard library and runtime library). You'd compile and statically link it via:

  1. main.cpp编译为main.o(输出文件名是隐式的):

  1. Compile main.cpp to main.o (the output file name is implicit):

$ g++ -c -Wall main.cpp

-c告诉GCC在编译步骤后停止(不运行链接器). -Wall打开大多数诊断消息.如果新手程序员会更频繁地使用它并更加注意它,那么就不会在此站点上提出很多问题了. ;-)

The -c tells GCC to stop after the compilation step (not run the linker). The -Wall turns on most diagnostic messages. If novice programmers would use it more often and pay more attention to it, many questions on this site would not have been asked. ;-)

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

Link main.o (could list more than one object file) statically pulling in the standard and runtime library and put the executable in the file main:

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

如果不使用-o main开关,GCC会将最终的可执行文件放入名称不太明确的文件a.out(该文件最终代表程序集输出").

Without using the -o main switch, GCC would have put the final executable in the not so well-named file a.out (which once eventually stood for "assembly output").

特别是在开始时,我强烈建议手动"执行此类操作,因为这将有助于更好地了解构建工具链.

Especially at the beginning, I strongly recommend doing such things "by hand" as it will help get a better understanding of the build tool-chain.

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

As a matter of fact, the above two commands could have been combined into just one:

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

任何合理的IDE都应具有用于指定此类编译器/链接器标志的选项.

Any reasonable IDE should have options for specifying such compiler / linker flags.

静态链接的原因:

  • 您只有一个文件,可以将其复制到具有兼容体系结构和操作系统的任何计算机上,并且无论安装了什么版本的库,它都可以正常工作.

  • You have a single file that can be copied to any machine with a compatible architecture and operating system and it will just work, no matter what version of what library is installed.

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

You can execute the program in an environment where the shared libraries are not available. For example, putting a statically linked CGI executable into a chroot() jail might help reduce the attack surface on a web server.

由于不需要动态链接,因此程序启动可能更快. (我确定在某些情况下情况恰恰相反,特别是如果共享库已经为另一个进程加载的话.)

Since no dynamic linking is needed, program startup might be faster. (I'm sure there are situations where the opposite is true, especially if the shared library was already loaded for another process.)

由于链接程序可以对函数地址进行硬编码,因此功能调用 可能会更快.

Since the linker can hard-code function addresses, function calls might be faster.

在安装了多个公共库版本(例如LAPACK)的系统上,静态链接可以帮助确保始终使用特定版本,而不必担心正确设置LD_LIBRARY_PATH.显然,这也是一个缺点,因为现在您不能在不重新编译的情况下不再选择该库.如果您始终想要相同的版本,那么为什么要首先安装多个版本?

On systems that have more than one version of a common library (LAPACK, for example) installed, static linking can help make sure that a specific version is always used without worrying about setting the LD_LIBRARY_PATH correctly. Obviously, this is also a disadvantage since now you cannot select the library any more without recompiling. If you always wanted the same version, why would you have installed more than one in the first place?

原因反对静态链接:

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

  • As you have already mentioned, the size of the executable might grow dramatically. This depends of course heavily on what libraries you link in.

如果多个进程同时需要该库,则操作系统可能足够聪明,可以将共享库的文本部分仅加载到RAM中一次.通过静态链接,您将失去这一优势,并且系统可能会更快地运行内存不足.

The operating system might be smart enough to load the text section of a shared library into the RAM only once if several processes need the library at the same time. By linking statically, you void this advantage and the system might run short of memory more quickly.

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

Your program no longer profits from library upgrades. Instead of simply replacing one shared library with a (hopefully ABI compatible) newer release, a system administrator will have to recompile and reinstall every program that uses it. This is the most severe drawback in my opinion.

例如考虑OpenSSL库.当Heartbleed错误于今年早些时候被发现并修复后,系统管理员可以在补丁发布后的一天之内安装OpenSSL的补丁版本并重新启动所有服务以修复该漏洞.也就是说,如果他们的服务是针对OpenSSL动态链接的.对于那些已经静态链接的程序,要花上几周的时间才能解决上一个问题,我可以肯定的是,仍然有野生的专有多合一"软件到目前为止还没有找到修复的解决方案.一天.

Consider for example the OpenSSL library. When the Heartbleed bug was discovered and fixed earlier this year, system administrators could install a patched version of OpenSSL and restart all services to fix the vulnerability within a day as soon as the patch was out. That is, if their services were linking dynamically against OpenSSL. For those that have been linked statically, it would have taken weeks until the last one was fixed and I'm pretty sure that there is still proprietary "all in one" software out in the wild that did not see a fix up to the present day.

您的用户无法即时替换共享库.例如,torsocks脚本(和关联的库)允许用户(通过适当地设置LD_PRELOAD)用通过Tor网络路由其流量的网络系统库替换(通过适当地设置LD_PRELOAD).这甚至适用于那些开发人员甚至从未想到过这种可能性的程序. (这是否安全,一个好主意是否引起了不相关的争论.)另一个常见的用例是通过使用专用版本替换malloc等来调试或强化"应用程序.

Your users cannot replace a shared library on the fly. For example, the torsocks script (and associated library) allows users to replace (via setting LD_PRELOAD appropriately) the networking system library by one that routes their traffic through the Tor network. And this even works for programs whose developers never even thought of that possibility. (Whether this is secure and a good idea is subject of an unrelated debate.) An other common use-case is debugging or "hardening" applications by replacing malloc and the like with specialized versions.

在我看来,除了非常特殊的情况外,静态链接的弊端大于所有优点.根据经验:可以动态链接,如果需要则可以静态链接.

In my opinion, the disadvantages of static linking outweigh the advantages in all but very special cases. As a rule of thumb: link dynamically if you can and statically if you have to.

正如 Alf 所指出的那样(请参见评论),有一个特殊的GCC选项可以有选择地静态链接C ++标准库,但不能静态链接整个程序.从 GCC手册:

As Alf has pointed out (see comments), there is a special GCC option to selectively link in the C++ standard library statically but not link the whole program statically. From the GCC manual:

-static-libstdc++

使用g ++程序链接C ++程序时,通常会自动针对libstdc ++进行链接.如果libstdc ++可用作共享库,并且未使用-static选项,则此链接指向libstdc ++的共享版本.通常没关系.但是,有时冻结程序使用的libstdc ++的版本而不必一直使用完全静态的链接是有用的. -static-libstdc++选项指示g ++驱动程序静态链接libstdc ++,而不必静态链接其他库.

When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.

这篇关于我如何将标准库静态链接到我的C ++程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆