Consider this empty program:
int main()
{ return 0; }
If I compile it with C++ with g++ main.cpp && strace ./a.out
, and analyze the output with strace
, I observed that the last lines of the output are (you can add -O3
that the effect is the same):
mprotect(0x7f71af154000, 45056, PROT_READ) = 0
mprotect(0x7f71af38b000, 4096, PROT_READ) = 0
brk(NULL) = 0xed2000
brk(0xf05000) = 0xf05000
exit_group(0) = ?
+++ exited with 0 +++
However, if I do instead: gcc main.cpp && strace ./a.out
mprotect(0x7f4114318000, 16384, PROT_READ) = 0
mprotect(0x7f4114547000, 4096, PROT_READ) = 0
exit_group(0) = ?
+++ exited with 0 +++
As you see, in C++ there's an extra brk
that extends the heap by exactly 204KB (0xf05000 - 0xed2000 = 204KB after translating both to decimal). That can be easily verified by replacing that program by (coliru link):
#include <iostream>
#include <unistd.h>
int main()
{
char buf[1024];
sprintf(buf, "pmap -XX %u", getpid());
std::system(buf);
return 0;
}
and you can easily observe that compiling with g++
the [heap]
has a size of 204KB, and with gcc
the [heap]
line even disappeared from the pmap
output.
NOTE: By the way, and to my surprise, gcc had no problem at all with include <iostream>
and with the presence of std
in std::system
.
What are these 204KB used for? Not worried or anything about these little 204KB but it caught my attention and I'm curious now.
Remove the libraries added by g++
and it will not do the extra allocation:
g++ -nodefaultlibs -lc main.cpp
With the default libraries, the C++ program gets linked to:
/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
Without the default libraries + libc
:
/lib64/ld-linux-x86-64.so.2
libc.so.6 => /lib64/libc.so.6
linux-vdso.so.1
The extra libraries being:
libgcc_s.so.1 => /lib64/libgcc_s.so.1
libm.so.6 => /lib64/libm.so.6
libstdc++.so.6 => /lib64/libstdc++.so.6
I wonder anyway which specific C++ lib increased the heap
By adding the extra libraries to the linking one at a time, we can see that it's libstdc++
that causes the extra allocation, so if you can get away without the compiled part of the C++ standard library, this is what you could use:
g++ -nodefaultlibs -lgcc_s -lm -lc
Single-stepping through the program compiled with the default libraries shows the construction and destruction of misc. standard C++ objects, such as this std::atomic<std::shared_ptr<std::chrono::tzdb_list::_Node>>
. The timezone database alone ought to take up a bit of space, but I'm not sure if that alone covers the full 204 KiB you observed. The conclusion is however that the C++ standard library has more objects (in addition to those in the C standard library) that are implicitly constructed (the standard iostream
s for example):
$ gdb -tui ./a.out
(gdb) layout asm
(gdb) start
(fiddling about for a long time)
(gdb) tui d
(gdb) bt
#0 std::atomic<std::shared_ptr<std::chrono::tzdb_list::_Node> >::~atomic (this=0x7ffff7e62810 <std::chrono::tzdb_list::_Node::_S_head_owner>, __in_chrg=<optimized out>)
at /usr/src/debug/gcc-14.2.1-3.fc40.x86_64/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:630
#1 0x00007ffff7a51e60 in __cxa_finalize (d=0x7ffff7e52200) at cxa_finalize.c:82
#2 0x00007ffff7cb4947 in __do_global_dtors_aux () from /lib64/libstdc++.so.6
#3 0x00007fffffffd750 in ?? ()
#4 0x00007ffff7fc90f2 in _dl_call_fini (closure_map=0x7ffff7f8a000) at dl-call_fini.c:43