[HN Gopher] Why is the first C++ (m)allocation always 72 KB?
       ___________________________________________________________________
        
       Why is the first C++ (m)allocation always 72 KB?
        
       Author : joelsiks
       Score  : 119 points
       Date   : 2026-03-01 09:27 UTC (13 hours ago)
        
 (HTM) web link (joelsiks.com)
 (TXT) w3m dump (joelsiks.com)
        
       | throwaway2037 wrote:
       | I would like the see the source code for libmymalloc.so, however,
       | I don't see anything in the blog post. Nor do I see anything in
       | his GitHub profile: https://github.com/jsikstro
       | 
       | Also, I cannot find his email address anywhere (to ask him to
       | share it on GitHub).
       | 
       | Am I missing something?
        
         | joelsiks wrote:
         | The exact implementation of mymalloc isn't relevant to the
         | post. I have an old allocator published at
         | https://github.com/joelsiks/jsmalloc that I did as part of my
         | Master's thesis, which uses a similar debug-logging mechanism
         | that is described in the post.
        
         | nly wrote:
         | dlsym() with the RTLD_NEXT flag basically:
         | 
         | https://catonmat.net/simple-ld-preload-tutorial-part-two
         | 
         | There's actually a better way to hook GNUs malloc:
         | 
         | https://www.man7.org/linux/man-pages/man3/malloc_hook.3.html
         | 
         | This is better because you can disable the hook inside the
         | callback, and therefore use malloc within your malloc hook (no
         | recursion)
         | 
         | But you can't use this mechanism before main()
        
           | Joker_vD wrote:
           | The use of these hook functions is not safe in multithreaded
           | programs, and they are now deprecated.  From glibc 2.24
           | onwards,         the __malloc_initialize_hook variable has
           | been removed from the         API, and from glibc 2.34
           | onwards, all the hook variables have been         removed
           | from the API.  Programmers should instead preempt calls to
           | the relevant functions by defining and exporting malloc(),
           | free(),         realloc(), and calloc().
        
             | nly wrote:
             | Yeah. Shame though because it gave you the option to
             | control exactly when you hooked and didn't hook, which let
             | stop and start debugging allocations based on arbitrary
             | triggers.
             | 
             | The global variable approach was very useful and pretty low
             | overhead.
        
               | jeffbee wrote:
               | If you only wanted to observe the behavior the post is
               | discussing, it seems like `ltrace -e malloc` is a lot
               | easier.
        
               | fweimer wrote:
               | You can still override malloc and call __libc_malloc if
               | you do not want to bother with dlsym/RTLD_NEXT. These
               | function aliases are undocumented, but for a quick
               | experiment, that shouldn't matter.
        
       | Joker_vD wrote:
       | Huh. Why is this emergency pool not statically allocated? Is it
       | possible to tune the size of this pool on libc++ startup somehow?
       | Because otherwise it absolutely should've been statically
       | allocated.
        
         | joelsiks wrote:
         | I did mention it briefly in the post, but you can opt-in for a
         | fixed-size statically allocated buffer by configuring libstdc++
         | with --enable-libstdcxx-static-eh-pool. Also, you can opt-out
         | of the pool entirely by configuring the number of objects in
         | the pool to zero with the environment variable
         | GLIBCXX_TUNABLES=glibcxx.eh_pool.obj_count=0.
        
           | ninkendo wrote:
           | I wonder why it's opt-in. Maybe it's part of the whole "you
           | only pay for what you use" ethos, i.e. you shouldn't have to
           | pay the cost for a static emergency pool if you don't even
           | use dynamic memory allocation.
        
       | pjmlp wrote:
       | This is compiler specific and cannot be generalised as C++.
        
         | compiler-guy wrote:
         | And C++ library specific as well. Perhaps even more so.
        
         | zabzonk wrote:
         | Well, yes, but still quite interesting, IMHO. It's not like GCC
         | is one of the least used compilers.
        
           | pjmlp wrote:
           | Yeah, but that isn't C++ in isolation, thus the tile is
           | incorrect.
        
             | appreciatorBus wrote:
             | Article has been updated
             | 
             | > EDIT (March 1, 2026): I updated the title to to clarify
             | that this observation is specific to my environment. The
             | original title may have implied a universal behavior, which
             | isn't the case. Thanks for the feedback!
        
               | pjmlp wrote:
               | Thanks for the update!
        
         | surajrmal wrote:
         | I would also expect it to depend on whether or not you have
         | exceptions enabled. Half the ecosystem has them disabled.
        
       | aliveintucson wrote:
       | I think you should read up on what "always" means.
        
       | znpy wrote:
       | > TLDR; The C++ standard library sets up exception handling
       | infrastructure early on, allocating memory for an "emergency
       | pool" to be able to allocate memory for exceptions in case malloc
       | ever runs out of memory.
       | 
       | Reminds me of Perl's $^M:
       | https://perldoc.perl.org/variables/$%5EM
       | 
       | In Perl you can "hand-manage" that. This line would allocate a
       | 64K buffer for use in an emergency:                   $^M = 'a' x
       | (1 << 16);
        
       | jebarker wrote:
       | Reading this was a good reminder not to be intimidated by
       | assumptions about complexity. (Without giving it much thought) I
       | would have assumed that it would be hard to replace malloc for
       | such fundamental applications as ls, but it's surprisingly
       | simple.
        
         | syncsynchalt wrote:
         | There's usually an easy-ish way to override
         | malloc/calloc/realloc/free on Unix, as it's very useful to do
         | when debugging issues or just to collect allocation metrics.
         | 
         | In ELF objects (i.e. on Linux) this is usually done with the
         | "Weak" symbol binding. This is an optional flag for symbols in
         | ELF format that let you override a symbol by providing a
         | competing non-weak symbol, which the linker will prefer when
         | there is a conflict. https://en.wikipedia.org/wiki/Weak_symbol
         | 
         | You can see the list of Weak symbols by looking for a 'W' in
         | the output of `nm` on linux hosts.
        
         | ozgrakkurt wrote:
         | This applies to a lot of things unfortunately. There is a cult
         | of just being afraid and scaring other people.
         | 
         | "You can't do it, just use a library.". "Just use this library,
         | everyone uses it.". "Even google uses this library, do you
         | think you are better." etc.
         | 
         | To add another example to this, you will read that memcpy is
         | super mega optimized on libc and you shouldn't do it yourself
         | etc. etc. etc.
         | 
         | But if you just check clickhouse [1] as an example. They
         | implemented it, it is pretty basic and they say it works well
         | in the comments of the code.
         | 
         | Also you can check musl libc code etc. and it is fairly simple.
         | 
         | People still would argue that you used some intrinsic so it
         | isn't portable or you just benchmarked on one case so it won't
         | work well overall.
         | 
         | Well you CAN benchmark as wide as you want inside your project
         | and have a different memcpy code per project. This kind of
         | thing isn't as bad as people make it out to be in my opinion.
         | 
         | Ofc memcpy is just an example here and it applies similarly to
         | memory allocation, io etc.
         | 
         | As a negative note, imo this is one of the major reasons why
         | most software is super crappy now. Everything uses some library
         | -> those libraries change all the time -> more breaking -> more
         | maintenance. Similar chain happens in terms of performance
         | because the person that wrote that library probably doesn't
         | even know how I am using the library.
         | 
         | This is also why people have endless arguments about what
         | library/tool to use while they can be learning more and more
         | things every day.
         | 
         | [1]
         | https://github.com/ClickHouse/ClickHouse/blob/master/base/gl...
        
         | userbinator wrote:
         | If you started learning from the "bottom-up", you wouldn't
         | think it's intimidating. Fortunately, it's never too late to
         | start learning.
        
       | anonymousiam wrote:
       | So basically, before any of the code even runs, this environment
       | begins by gobbling up more than the total RAM that most of my
       | first computers had (SYM-1, IAMSAI-8080, Ferguson Big Board,
       | Kaypro II, and CCS S-100 Z-80). All of these systems were 8-bit,
       | with various RAM sizes from 8KB to 64KB. That was the maximum RAM
       | available, and it was shared by the OS and the applications.
        
         | surajrmal wrote:
         | What's the purpose of making such a comparison? The implication
         | is that we're being wasteful, but I'm not certain that's the
         | point you're trying to make.
        
       | cendyne wrote:
       | This was a fun little share. Thanks for writing it up!
        
       ___________________________________________________________________
       (page generated 2026-03-01 23:01 UTC)