https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118854
Bug ID: 118854 Summary: ASAN heap-after-use in shared_ptr copy constructor when copying a shared_ptr constructed with make_shared Product: gcc Version: 14.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: nicholas at nicholaswilliams dot net Target Milestone: --- Created attachment 60480 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60480&action=edit shared_ptr_segfault.cpp Profuse apologies if I've actually found a bug in AddressSanitizer, but I'm 99.5% sure the bug is in shared_ptr or, at least, in some atomic resource it is using. In an (admittedly extreme) edge case, I can reliably get shared_ptr's copy constructor to trigger a heap-after-use error when copying a static shared_ptr as it is destructed by libstdc++ internals at application shutdown. Interestingly, without address sanitizer, I have not been able to get this to trigger a segfault. I think that's a timing issue and it would, eventually, segfault, but I can't prove that. My simple replication program (attached) does trigger the ASAN error every time. I'm reporting this against GCC 14.2.1 because that's the latest version currently installed in our architecture, but I've also duplicated with the exact same code in GCC 13, GCC 11, and even Apple Clang 16 (which uses some variation/fork of libstdc++ but is failing in the exact same way with a slightly different stack within the shared_ptr copy constructor). This was compiled with: $ g++ -v -std=c++20 -g -fsanitize=address -fsanitize-address-use-after-scope -Wall -Wextra -Werror -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_DEBUG -o shared_ptr_segfault shared_ptr_segfault.cpp If I reverse the order of these two statements: BackgroundThread gBackgroundThread; std::shared_ptr< Resource > Resource:: _pInstance = std::make_shared< Resource >(); Or use __attribute__((init_priority)) to control their init order, the problem goes away. I can do something like that in my real-world use case, but IMO the shared_ptr copy constructor should not exhibit this problem in any case. It should yield a shared_ptr managing nothing if the original shared_ptr is destructing or a complete copy of the shared_ptr otherwise. I even had an initial instinct, "Oh, I should be protecting `_pInstance` with a mutex," but of course that achieves nothing, because it's libstdc++ internals that are destructing the static shared_ptr, not any code over which I have control, and so the destructing code does not know or care about the mutex. .cpp file, gcc -v output, and runtime output attached.