https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118811
--- Comment #11 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Nicholas Williams from comment #0) > Created attachment 60437 [details] > Minimal reproduction application > > I have discovered a SIGABRT (or, when ASAN is enabled, a heap-use-after-free > report) in std::chrono::locate_zone() when it calls > std::chrono::tzdb_list::begin() as a result of C++20 Chrono library use > during application shutdown (exit handlers). I'm not able to attach our > proprietary code, so I have attached a fully functional minimal replication > application that successfully demonstrates the problem. Doesn't your minimized program have a data race on the _running member? _pInstance is also accessed without synchronization but is only accessed from the main thread so that doesn't have a data race. > From what I can tell reading through the ASAN report and the code in the > chrono header, the problem appears to be related to the use of a chrono > class's private static class data member that's a shared_ptr, without any > checks about the validity of said shared_ptr. Since static class data > members are destructed before static global variables, Are they? Where is that specified? > the shared_ptr in > chrono gets destructed before our logging thread shared_ptr. Like all objects with static storage duration, it gets destroyed in reverse order of construction. Because your logging thread shared_ptr is created early, before main, it is constructed in an unspecified order compared to any other globals, including the tzdb_list pointer. As Andrew said, there's a static initialization order bug. This should be fixable by using __attribute__((init_priority(x))) inside libstdc++.