考虑这个空程序:
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 和in<iostream>
的存在完全没有问题。std
std::system
这 204KB 是用来做什么的?我对这 204KB 一点也不担心,但它引起了我的注意,现在我很好奇。
删除添加的库
g++
,它将不会进行额外的分配:使用默认库,C++ 程序将链接到:
没有默认库 +
libc
:额外的库包括:
通过一次将额外的库添加到链接中,我们可以看到它
libstdc++
导致了额外的分配,所以如果你可以不用 C++ 标准库的编译部分,那么你可以使用以下内容:使用默认库编译的程序单步执行显示了各种标准 C++ 对象的构造和销毁,例如这个
std::atomic<std::shared_ptr<std::chrono::tzdb_list::_Node>>
。仅时区数据库就应该占用一些空间,但我不确定它是否能覆盖您观察到的全部 2 KiB。然而,结论是 C++ 标准库有更多对象(除了 C 标准库中的对象)是隐式构造的(iostream
例如标准 s):