c++clinuxgccheap-memory

An empty program that does nothing in C++ needs a heap of 204KB but not in C


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.


Solution

  • This is due to the emergency buffer allocated by the C++ language runtime. When an exception is thrown, the runtime makes a copy of the thrown object in dynamically allocated memory. If it is unable to dynamically allocate enough memory, the GCC implementation falls back to allocating space from an emergency buffer it allocates at program startup. If that fails, it calls std::terminate().

    This behaviour is implementation-defined. You will find other C++ language runtime implementations may do things differently.