考虑这个空程序:
int main()
{ return 0; }
如果我用C++用
g++ main.cpp && strace ./a.out
编译它,并用strace
分析输出,我观察到输出的最后几行是(你可以添加-O3
,效果是一样的):
mprotect(0x7f71af154000, 45056, PROT_READ) = 0
mprotect(0x7f71af38b000, 4096, PROT_READ) = 0
brk(NULL) = 0xed2000
brk(0xf05000) = 0xf05000
exit_group(0) = ?
+++ exited with 0 +++
但是,如果我这样做:
gcc main.cpp && strace ./a.out
mprotect(0x7f4114318000, 16384, PROT_READ) = 0
mprotect(0x7f4114547000, 4096, PROT_READ) = 0
exit_group(0) = ?
+++ exited with 0 +++
如您所见,在 C++ 中,有一个额外的
brk
将堆精确扩展了 204KB(将两者转换为十进制后,0xf05000 - 0xed2000 = 204KB)。通过用(coliru链接)替换该程序可以轻松验证这一点:
#include <iostream>
#include <unistd.h>
int main()
{
char buf[1024];
sprintf(buf, "pmap -XX %u", getpid());
std::system(buf);
return 0;
}
并且您可以轻松观察到使用
g++
进行编译,[heap]
的大小为 204KB,而使用 gcc
时,[heap]
行甚至从 pmap
输出中消失了。
注意: 顺便说一句,令我惊讶的是,gcc 对于 include
<iostream>
以及 std
中存在 std::system
完全没有问题。
这204KB有什么用呢?不担心这些 204KB 的小东西,但它引起了我的注意,我现在很好奇。
删除
g++
添加的库,它不会进行额外的分配:g++ -nodefaultlibs -lc main.cpp
。
使用默认库,C++ 程序会链接到:
/lib64/ld-linux-x86-64.so.2
libc.so.6 => /lib64/libc.so.6
libgcc_s.so.1 => /lib64/libgcc_s.so.1
libm.so.6 => /lib64/libm.so.6
libstdc++.so.6 => /lib64/libstdc++.so.6
linux-vdso.so.1
没有默认库 +
libc
:
/lib64/ld-linux-x86-64.so.2
libc.so.6 => /lib64/libc.so.6
linux-vdso.so.1
额外的库是:
libgcc_s.so.1 => /lib64/libgcc_s.so.1
libm.so.6 => /lib64/libm.so.6
libstdc++.so.6 => /lib64/libstdc++.so.6
无论如何,我想知道哪个特定的 C++ 库增加了堆
通过一次将一个额外的库添加到链接库中,我们可以看到,正是
libstdc++
导致了额外的分配,因此,如果您可以在没有 C++ 标准库的已编译部分的情况下逃脱,这就是您所要做的可以使用:
g++ -nodefaultlibs -lgcc_s -lm -lc