Startup crash on macOS with GCC 15.2: `std::source_location::file_name()` is `nullptr` #33964

issue l0rinc opened this issue on November 27, 2025
  1. l0rinc commented at 7:44 PM on November 27, 2025: contributor

    Summary

    bitcoind crashes on startup when built with Homebrew GCC 15.2.0 on macOS (arm64). The crash occurs inside SourceLocationHasher::operator() when constructing a std::basic_string_view from std::source_location::file_name().

    The same commit runs successfully when built with the default AppleClang toolchain.

    Versions

    • Bitcoin Core: master at 808f1d972be35f4c66bdc30ab0f4060dab0c43c0
    • Platform: macOS 26.1 (25B78), Apple M4 Pro (arm64)
    • CMake: cmake version 4.2.0
    • GCC: gcc (Homebrew GCC 15.2.0) 15.2.0
    • AppleClang: AppleClang 17.0.0.17000404

    Build configuration (GCC 15.2, Debug)

    git checkout 808f1d972be35f4c66bdc30ab0f4060dab0c43c0
    rm -rfd build && cmake -B build -DENABLE_IPC=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ && cmake --build build -j$(nproc)             
    lldb ./build/bin/bitcoind -- -datadir="$HOME/Library/Application Support/Bitcoin" -stopatheight=21129 -dbcache=1000 -printtoconsole=1
    

    Crash session

    (lldb) run
    Process 4126 launched: '/Users/lorinc/IdeaProjects/bitcoin/build/bin/bitcoind' (arm64)
    2025-11-27T19:01:48Z Bitcoin Core version v30.99.0-b3e2ae7aaee5 (debug build)
    2025-11-27T19:01:48Z Using the 'arm_shani(1way;2way)' SHA256 implementation
    2025-11-27T19:01:48Z Default data directory /Users/lorinc/Library/Application Support/Bitcoin
    2025-11-27T19:01:48Z Using data directory /Users/lorinc/Library/Application Support/Bitcoin
    2025-11-27T19:01:48Z Config file: /Users/lorinc/Library/Application Support/Bitcoin/bitcoin.conf (not found, skipping)
    2025-11-27T19:01:48Z Command-line arg: datadir="/Users/lorinc/Library/Application Support/Bitcoin"
    2025-11-27T19:01:48Z Command-line arg: dbcache="1000"
    2025-11-27T19:01:48Z Command-line arg: printtoconsole="1"
    2025-11-27T19:01:48Z Command-line arg: stopatheight="21129"
    2025-11-27T19:01:48Z Using at most 125 automatic connections (1024 file descriptors available)
    2025-11-27T19:01:48Z scheduler thread start
    2025-11-27T19:01:48Z Binding RPC on address ::1 port 8332
    2025-11-27T19:01:48Z Binding RPC on address 127.0.0.1 port 8332
    2025-11-27T19:01:48Z Generated RPC authentication cookie /Users/lorinc/Library/Application Support/Bitcoin/.cookie
    2025-11-27T19:01:48Z Permissions used for cookie: rw-------
    2025-11-27T19:01:48Z Using random cookie authentication.
    2025-11-27T19:01:48Z Starting HTTP server with 16 worker threads
    Process 4126 stopped
    * thread [#1](/bitcoin-bitcoin/1/), queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
        frame [#0](/bitcoin-bitcoin/0/): 0x000000019fb3ca84 libsystem_platform.dylib`_platform_strlen + 4
    libsystem_platform.dylib`_platform_strlen:
    ->  0x19fb3ca84 <+4>:  ldr    q0, [x1]
        0x19fb3ca88 <+8>:  adr    x3, 0x19fb3c9c0 ; ___lldb_unnamed_symbol_1804e09c0
        0x19fb3ca8c <+12>: ldr    q2, [x3], [#0](/bitcoin-bitcoin/0/)x10
        0x19fb3ca90 <+16>: and    x2, x0, [#0](/bitcoin-bitcoin/0/)xf
    (lldb) bt
    error: libbitcoin_util.a(logging.cpp.o) 0x4000ec000000034a: DW_TAG_member '_M_local_buf' refers to type 0x00000000000fed84 which extends beyond the bounds of 0x4000ec0000000340
    * thread [#1](/bitcoin-bitcoin/1/), queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
      * frame [#0](/bitcoin-bitcoin/0/): 0x000000019fb3ca84 libsystem_platform.dylib`_platform_strlen + 4
        frame [#1](/bitcoin-bitcoin/1/): 0x0000000100002600 bitcoind`std::char_traits<char>::length(__s=0x0000000000000000) at char_traits.h:393:25
        frame [#2](/bitcoin-bitcoin/2/): 0x00000001000086d0 bitcoind`std::basic_string_view<char, std::char_traits<char>>::basic_string_view(this=0x000000016fdfa1b8, __str=0x0000000000000000) at string_view:145:35
        frame [#3](/bitcoin-bitcoin/3/): 0x0000000100f43634 bitcoind`SourceLocationHasher::operator()(this=0x000000081286d8a0, s=0x000000016fdfa820) const at logging.h:52:74
        frame [#4](/bitcoin-bitcoin/4/): 0x0000000100f554c0 bitcoind`std::__detail::_Hash_code_base<std::source_location, std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>, std::__detail::_Select1st, SourceLocationHasher, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_hash_code(this=0x000000081286d8a0, __k=0x000000016fdfa820) const at hashtable_policy.h:1071:23
        frame [#5](/bitcoin-bitcoin/5/): 0x0000000100f50a08 bitcoind`std::_Hashtable<std::source_location, std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>, std::allocator<std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>>, std::__detail::_Select1st, SourceLocationEqual, SourceLocationHasher, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>>::_M_locate(this=0x000000081286d8a0, __k=0x000000016fdfa820) const at hashtable.h:2279:46
        frame [#6](/bitcoin-bitcoin/6/): 0x0000000100f4d3ec bitcoind`std::pair<std::__detail::_Node_iterator<std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>, false, false>, bool> std::_Hashtable<std::source_location, std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>, std::allocator<std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>>, std::__detail::_Select1st, SourceLocationEqual, SourceLocationHasher, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>>::try_emplace<std::source_location const&, unsigned long long const&>(this=0x000000081286d8a0, (null)=std::_Hashtable<std::source_location, std::pair<const std::source_location, BCLog::LogRateLimiter::Stats>, std::allocator<std::pair<const std::source_location, BCLog::LogRateLimiter::Stats> >, std::__detail::_Select1st, SourceLocationEqual, SourceLocationHasher, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::const_iterator @ 0x000000016fdfa2a0, __k=0x000000016fdfa820, (null)=0x000000081286d8e0) at hashtable.h:1088:30
        frame [#7](/bitcoin-bitcoin/7/): 0x0000000100f4ac1c bitcoind`std::pair<std::__detail::_Node_iterator<std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>, false, false>, bool> std::unordered_map<std::source_location, BCLog::LogRateLimiter::Stats, SourceLocationHasher, SourceLocationEqual, std::allocator<std::pair<std::source_location const, BCLog::LogRateLimiter::Stats>>>::try_emplace<unsigned long long const&>(this=size=0, __k=0x000000016fdfa820, (null)=0x000000081286d8e0) at unordered_map.h:527:27
        frame [#8](/bitcoin-bitcoin/8/): 0x0000000100f47510 bitcoind`BCLog::LogRateLimiter::Consume(this=0x000000081286d860, source_loc=0x000000016fdfa820, str="2025-11-27T19:01:48Z Using wallet directory /Users/lorinc/Library/Application Support/Bitcoin/wallets\n") at logging.cpp:395:47
        frame [#9](/bitcoin-bitcoin/9/): 0x0000000100f47e20 bitcoind`BCLog::Logger::LogPrintStr_(this=0x0000000812820c80, str=(_M_len = 80, _M_str = "Using wallet directory /Users/lorinc/Library/Application Support/Bitcoin/wallets"), source_loc=0x000000016fdfa820, category=ALL, level=Info, should_ratelimit=true) at logging.cpp:465:39
        frame [#10](/bitcoin-bitcoin/10/): 0x0000000100f47a24 bitcoind`BCLog::Logger::LogPrintStr(this=0x0000000812820c80, str=(_M_len = 80, _M_str = "Using wallet directory /Users/lorinc/Library/Application Support/Bitcoin/wallets"), source_loc=0x000000016fdfa820, category=ALL, level=Info, should_ratelimit=true) at logging.cpp:426:24
        frame [#11](/bitcoin-bitcoin/11/): 0x000000010001daec bitcoind`void LogPrintFormatInternal<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>(source_loc=0x000000016fdfa820, flag=ALL, level=Info, should_ratelimit=true, fmt=(fmt = "Using wallet directory %s"), (null)="/Users/lorinc/Library/Application Support/Bitcoin/wallets") at logging.h:358:34
        frame [#12](/bitcoin-bitcoin/12/): 0x000000010098b85c bitcoind`wallet::VerifyWallets(context=0x00000008130101c8) at load.cpp:53:5
        frame [#13](/bitcoin-bitcoin/13/): 0x0000000100931d4c bitcoind`wallet::(anonymous namespace)::WalletLoaderImpl::verify(this=0x00000008130101c0) const at interfaces.cpp:558:50
        frame [#14](/bitcoin-bitcoin/14/): 0x0000000100173c10 bitcoind`AppInitMain(node=0x000000016fdfea08, tip_info=0x0000000000000000) at init.cpp:1523:28
        frame [#15](/bitcoin-bitcoin/15/): 0x0000000100009820 bitcoind`AppInit(node=0x000000016fdfea08) at bitcoind.cpp:242:54
        frame [#16](/bitcoin-bitcoin/16/): 0x0000000100009c54 bitcoind`main(argc=5, argv=0x000000016fdff1c0) at bitcoind.cpp:283:17
        frame [#17](/bitcoin-bitcoin/17/): 0x000000019f76dd54 dyld`start + 7184
    

    On this toolchain, file_name() returns a null pointer, so std::basic_string_view calls std::char_traits<char>::length(__s = 0x0)strlen(nullptr), which triggers EXC_BAD_ACCESS.


    According to cppreference for std::source_location::file_name, the function is specified to:

    Return the name of the current source file represented by this object, represented as a null-terminated byte string.

  2. maflcko commented at 8:33 PM on November 27, 2025: member

    Your toolchain clearly violates the C++ standard (https://eel.is/c++draft/support.srcloc#class.general-2), so you'll have to report this upstream via a minimal reproducer.

  3. maflcko added the label macOS on Nov 27, 2025
  4. maflcko added the label Upstream on Nov 27, 2025
  5. maflcko added the label Questions and Help on Nov 27, 2025
  6. l0rinc commented at 11:53 AM on November 30, 2025: contributor

    Tried getting to the bottom of it, something's really off here, two consecutive calls to std::source_location::current() return very different and suspicious values: <img width="902" height="584" alt="Image" src="https://github.com/user-attachments/assets/cbd0798c-c86a-44f2-8874-618a2676dff8" />

    What does BTC file name and sat function name refer to and why do we have millions of lines :/?

    They seem to come from (modifying these strings updates the file and method names): https://github.com/bitcoin/bitcoin/blob/966666de9a6211b8748f43d682490c924e132e58/src/policy/feerate.h#L18-L19

    <details> <summary>source_location::current() manual instrumentation</summary>

    diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
    index 37cacb2a7e..19a9523322 100644
    --- a/src/bitcoind.cpp
    +++ b/src/bitcoind.cpp
    @@ -239,6 +239,10 @@ static bool AppInit(NodeContext& node)
                 // If locking a directory failed, exit immediately
                 return false;
             }
    +
    +        auto x = std::source_location::current();
    +        std::cout << "AppInit called from " << x.file_name() << ":" << x.line() << "\n";
    +
             fRet = AppInitInterfaces(node) && AppInitMain(node);
         }
         catch (const std::exception& e) {
    @@ -279,6 +283,9 @@ MAIN_FUNCTION
         // Process early info return commands such as -help or -version
         if (ProcessInitCommands(*init, args)) return EXIT_SUCCESS;
     
    +    auto x = std::source_location::current();
    +    std::cout << "main called from " << x.file_name() << ":" << x.line() << "\n";
    +
         // Start application
         if (!AppInit(node) || !Assert(node.shutdown_signal)->wait()) {
             node.exit_status = EXIT_FAILURE;
    diff --git a/src/init.cpp b/src/init.cpp
    index d1c6a5cad0..2c446785b0 100644
    --- a/src/init.cpp
    +++ b/src/init.cpp
    @@ -1518,6 +1518,10 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
                 return InitError(_("Unable to start HTTP server. See debug log for details."));
         }
     
    +    auto x = std::source_location::current();
    +    std::cout << "AppInitMain called from " << x.file_name() << ":" << x.line() << "\n";
    +
    +
         // ********************************************************* Step 5: verify wallet database integrity
         for (const auto& client : node.chain_clients) {
             if (!client->verify()) {
    diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp
    index 2cda1ba299..b353b51f28 100644
    --- a/src/wallet/interfaces.cpp
    +++ b/src/wallet/interfaces.cpp
    @@ -555,7 +555,13 @@ public:
                 m_rpc_handlers.emplace_back(m_context.chain->handleRpc(m_rpc_commands.back()));
             }
         }
    -    bool verify() override { return VerifyWallets(m_context); }
    +    bool verify() override
    +    {
    +        auto x = std::source_location::current();
    +        std::cout << "verify called from " << x.file_name() << ":" << x.line() << "\n";
    +
    +        return VerifyWallets(m_context);
    +    }
         bool load() override { return LoadWallets(m_context); }
         void start(CScheduler& scheduler) override
         {
    diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
    index f362064473..8a6a237d1d 100644
    --- a/src/wallet/load.cpp
    +++ b/src/wallet/load.cpp
    @@ -26,6 +26,12 @@ using util::Join;
     namespace wallet {
     bool VerifyWallets(WalletContext& context)
     {
    +    auto x1 = std::source_location::current();
    +    std::cout << "VerifyWallets1 called from " << x1.file_name() << ":" << x1.line() << "\n";
    +
    +    auto x = std::source_location::current();
    +    std::cout << "VerifyWallets called from " << x.file_name() << ":" << x.line() << "\n";
    +
         interfaces::Chain& chain = *context.chain;
         ArgsManager& args = *Assert(context.args);
    
    

    </details>

    The stack parents seem to be evaluated correctly, but VerifyWallets starts returning weird values from the start:

    main called from ./bitcoind.cpp:286
    AppInit called from ./bitcoind.cpp:243
    AppInitMain called from ./init.cpp:1521
    verify called from ./wallet/interfaces.cpp:560
    VerifyWallets1 called from BTC:4412482
    

    Doing the same with default AppleClang works correctly:

    <img width="1111" height="585" alt="Image" src="https://github.com/user-attachments/assets/e941f630-ff1e-4c47-9076-a93839912570" />


    I'm not sure how to create a reproducer for this...

  7. maflcko commented at 8:35 AM on December 1, 2025: member

    I'm not sure how to create a reproducer for this...

    For toolchain bugs, it helps to create a minimal reproducer. Often, this is easy to create in one shot, looking at the code that mis-compiled.

    Sometimes, it is not so easy and you'll have to manually remove chunks from the full software, until you end up with something minimal. This may be tedious, when done manually. You can also use creduce, but this may not work in contexts where one can define a unique bug signature (https://github.com/bitcoin/bitcoin/issues/32276#issuecomment-2812024548).

    In theory, it should be possible to move the runtime bug to a compile time bug with a static_assert(std::string_view{__FILE__}== std::string_view{std::source_location::current().file_name()});, so that it can be fed into creduce, but I have a feeling that the bug disappears at compile time. In that case, I don't see an easier way to reduce it.

  8. maflcko commented at 8:35 AM on December 1, 2025: member

    Unrelated, you can also try different version of your gcc package, to see if this was introduced recently.

  9. l0rinc commented at 9:53 AM on December 1, 2025: contributor

    Not sure how to create a reliable reproducer for this, closing for now

  10. l0rinc closed this on Dec 1, 2025


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 18:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me