我正在使用Code::Blocks IDE(v13.12)和GNU GCC编译器。
- 我想要链接程序所需的运行时库的静态版本,如何实现?
- 我已经知道我的可执行文件大小会增加。请告诉我其他的缺点。
- 在Visual C++ Express中这样做怎么样?
我正在使用Code::Blocks IDE(v13.12)和GNU GCC编译器。
由于还没有其他人给出答案,我来试着回答一下。不幸的是,我不熟悉Code::Blocks IDE,所以我的答案只能是部分的。
这并不是特定于IDE的,而是适用于GCC(以及许多其他编译器)的通用方法。假设您有一个简单的“hello, world”程序在main.cpp
中(除了标准库和运行时库之外没有外部依赖项)。您可以通过以下方式进行编译和静态链接:
Compile main.cpp
to main.o
(the output file name is implicit):
$ g++ -c -Wall main.cpp
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. ;-)
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
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”).
$ g++ -Wall -o main main.cpp -static
任何合理的 IDE 都应该有指定编译器/链接器标志的选项。
静态链接的优点:
您有一个单一的文件,可以复制到任何具有兼容架构和操作系统的机器上,并且它将正常工作,无论安装了什么版本的库。
您可以在没有共享库的环境中执行程序。例如,将静态链接的CGI可执行文件放入chroot()
监狱中可能有助于减少Web服务器的攻击面。
由于不需要动态链接,因此程序启动可能更快。 (我确信在其他进程已经加载共享库的情况下,相反的情况也是存在的。)
由于链接器可以硬编码函数地址,因此函数调用可能更快。
对于安装了多个通用库(例如LAPACK)版本的系统,静态链接可以帮助确保始终使用特定版本,而不必担心正确设置LD_LIBRARY_PATH
。显然,这也是一个缺点,因为现在您不能再选择库而不重新编译。 如果您始终想要相同的版本,为什么首先会安装多个版本呢?
反对静态链接的原因:
正如你已经提到的,可执行文件的大小可能会急剧增长。这当然严重依赖于你链接了哪些库。
如果多个进程同时需要同一个共享库,则操作系统可能足够聪明,只将共享库的文本部分加载到RAM一次。通过静态链接,你会失去这种优势,系统可能更快地耗尽内存。
你的程序不再受益于库的升级。系统管理员不再仅仅用一个(希望ABI兼容的)新版本替换一个共享库,而是必须重新编译并重新安装使用它的每个程序。在我看来,这是最严重的缺点。
例如,考虑OpenSSL库。今年早些时候发现并修复了Heartbleed漏洞时,系统管理员可以安装修补后的OpenSSL版本,并重新启动所有服务以在一天内修复漏洞。也就是说,如果他们的服务与OpenSSL动态链接。对于那些被静态链接的服务,需要几周时间才能全部修复,我非常确定,甚至今天还有一些专有的“全能软件”没有得到修复。
用户无法即时替换共享库。例如,torsocks
脚本(和相关库)允许用户通过适当设置LD_PRELOAD
来替换网络系统库,从而将其流量路由到Tor网络。这甚至适用于开发者从未考虑过这种可能性的程序。(无论这是否安全以及是否是一个好主意,都是另一个不相关的辩论。)另一个常见的用例是通过使用专门版本替换malloc
等来调试或“加固”应用程序。
-static-libstdc++
当使用g++程序链接C++程序时,通常会自动链接到libstdc++。如果libstdc++可用作共享库,并且未使用
-static
选项,则链接到libstdc++的共享版本。这通常是可以的。然而,有时候需要冻结程序使用的libstdc++版本,而不必完全静态链接。-static-libstdc++
选项指示g++驱动程序在不必静态链接其他库的情况下静态链接libstdc++。
-static
对于C++程序是否足够?或者还有其他选项可以实现C++标准库吗? - Cheers and hth. - Alfecho 'int main() {}' > main.cpp && gcc main.cpp -static && ldd a.out
显示没有动态链接。(与不使用 -static
进行比较。)或者,尝试使用一个简单的“hello, world”程序(在一个空目录中)链接和不链接 -static
,并使用 su --command="chroot $PWD ./a.out"
。这是你的意思吗? - 5gon12eder