A seemingly innocuous initial memory allocation of 73,728 bytes consistently occurs in nearly every C++ program on Linux, a quirk stemming from the standard library’s exception handling infrastructure, according to recent analysis by software engineer Joel Krähemann.
Krähemann, while experimenting with custom memory allocators and debugging tools, noticed the recurring allocation across diverse programs. His investigation, detailed in a personal blog post, traced the allocation to libstdc++, the GNU Standard C++ Library. The initial allocation isn’t a program-specific request, but rather a preemptive measure by the library to establish an “emergency pool” of memory.
The emergency pool is designed to ensure that exceptions can still be thrown, even if the standard memory allocation functions (like malloc) fail. According to libstdc++ source code, the pool is allocated lazily at program startup, when memory is generally more available. If an exception is triggered and the standard malloc call fails, the exception object is allocated from this pre-reserved pool. This provides a last-ditch effort to handle errors gracefully.
The size of the emergency pool – approximately 72 KB – is determined by a combination of factors, including the system’s word size and pre-defined constants within libstdc++. These constants, EMERGENCY_OBJ_SIZE and EMERGENCY_OBJ_COUNT, dictate the estimated size and number of exception objects the pool should accommodate. The pool’s size can be adjusted via the GLIBCXX_TUNABLES environment variable, as Krähemann demonstrated, reducing the initial allocation to 2,880 bytes by modifying the object count.
The behavior has been a source of confusion for developers, sometimes misinterpreted as a memory leak. Posts on online forums, such as Reddit’s r/cpp_questions, highlight developers encountering this unexplained allocation. Valgrind, a popular memory debugging tool, previously reported this memory as “still reachable” rather than a leak, further contributing to the misunderstanding. Newer versions of Valgrind now explicitly free the emergency pool during cleanup, providing more accurate reports, according to Krähemann’s research.
The emergency pool is specific to programs utilizing libstdc++. Programs written in C, or those using an alternative C++ standard library like libc++, may not exhibit this behavior. Krähemann notes that his custom allocator, implemented in C++, inherently relies on libstdc++, triggering the emergency pool allocation. A C-based allocator would only encounter this allocation when testing C++ binaries linked against libstdc++.
The libstdc++ source code includes a mechanism, __gnu_cxx::__freeres, to free the emergency pool when appropriate, and is called by Valgrind during cleanup. This function is conditionally compiled and only active when not using a static emergency pool.