https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77726
--- Comment #2 from Liu Hao <lh_mouse at 126 dot com> --- It isn't weired if you know how a Dynamic-Link Library (DLL) on Windows works different than a Shared Object (SO) on Linux. Windows does not have a dynamic linker such as `ld.so` on Linux. Symbols in a DLL are resolved at build-time, in contrary to Linux, where symbols in a SO are resolved at load-time. The DLL loader can resolve symbols to addresses, but it isn't as powerful as linkers after all. Consequently, an executable cannot use its strong symbols to override already-resolved weak ones in a DLL. If the user does not define a sized deallocation function, the default one in libstdc++*.dll is used, which calls the weak, default, non-sized deallocation function in the same DLL, which is the only candidate when the DLL is built and can't be overridden. Possible solution: The default sized deallocation function should not call the non-sized one directly. We may introduce a static pointer-to-function which points to the non-sized one initially. The default sized deallocation function should read that pointer then call the function it points to. An executable that defines a non-sized deallocation function should modify that pointer to point to the user-provided non-sized deallocation function before any other code that may allocate dynamic memory, possibly via an implicitly generated __constructor__ with high priority. Question: What will happen if both the executable and another DLL try to replace the non-sized deallocation function? It looks to me that on Linux such scenario will end up in multiple definitions. In this case abort() or std::terminate() is possibly solution.