<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/115992>115992</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [LSAN] LeakSanitizer false positive on macOS
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          madsmtm
      </td>
    </tr>
</table>

<pre>
    Building and running any program with LeakSanitizer or with AddressSanitizer's `detect_leaks=1` shows a leak in the system library `libobjc.A.dylib`.

I tested this in a virtual machine as well, this problem is present in at least macOS 13.5, macOS 14.7 and macOS 15.1.

It _may_ be an actual issue in the OS (though I doubt it), but ideally LeakSanitizer should filter it out anyhow, since it's not actionable for the user.

<details><summary>Full backtrace on macOS 15.1 (build 24B2083)</summary>
<p>

```console
$ echo "int main() { return 0; }" > foo.c               
$ /opt/homebrew/opt/llvm/bin/clang -fsanitize=leak foo.c
$ ./a.out
a.out(5340,0x1f228bac0) malloc: nano zone abandoned due to inability to reserve vm space.

=================================================================
==5340==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x0001030180f8 in malloc+0x60 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x340f8)
    #1 0x00018cf6fa8c in _malloc_type_malloc_outlined+0x60 (libsystem_malloc.dylib:arm64+0x1ca8c)
    #2 0x00018cd7aaf4 in _fetchInitializingClassList(bool)+0x34 (libobjc.A.dylib:arm64+0xaaf4)
 #3 0x00018cd7a9b8 in _setThisThreadIsInitializingClass(objc_class*)+0x1c (libobjc.A.dylib:arm64+0xa9b8)
    #4 0x00018cd7a7d4 in initializeNonMetaClass+0x234 (libobjc.A.dylib:arm64+0xa7d4)
    #5 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #6 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #7 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #8 0x00018cd98a38 in initializeAndMaybeRelock(objc_class*, objc_object*, locker_mixin<lockdebug::lock_mixin<objc_lock_base_t>>&, bool)+0xa0 (libobjc.A.dylib:arm64+0x28a38)
    #9 0x00018cd79f94 in lookUpImpOrForward+0x12c (libobjc.A.dylib:arm64+0x9f94)
    #10 0x00018cd79b80 in _objc_msgSend_uncached+0x40 (libobjc.A.dylib:arm64+0x9b80)
    #11 0x00018ce4bd54 in _xpc_collect_images+0xc0 (libxpc.dylib:arm64+0x2d54)
    #12 0x00018ce4b1b0 in _libxpc_initializer+0x424 (libxpc.dylib:arm64+0x21b0)
 #13 0x00019ac0d634 in libSystem_initializer+0xfc (libSystem.B.dylib:arm64+0x1634)
    #14 0x00018cddfd50 in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x110 (dyld:arm64+0xfffffffffff57d50)
    #15 0x00018ce1e4cc in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x150 (dyld:arm64+0xfffffffffff964cc)
 #16 0x00018ce11c34 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x1ec (dyld:arm64+0xfffffffffff89c34)
 #17 0x00018cdc42d8  (<unknown module>)
    #18 0x00018ce10bc8 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xbc (dyld:arm64+0xfffffffffff88bc8)
 #19 0x00018ce1dfe0 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x200 (dyld:arm64+0xfffffffffff95fe0)
 #20 0x00018cddfbb0 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xac (dyld:arm64+0xfffffffffff57bb0)
    #21 0x00018cdeabe4 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x28 (dyld:arm64+0xfffffffffff62be4)
    #22 0x00018cdff8b4 in dyld4::APIs::runAllInitializersForMain()+0x50 (dyld:arm64+0xfffffffffff778b4)
    #23 0x00018cdc98c4  (<unknown module>)
    #24 0x00018cdc8bbc  (<unknown module>)
    #25 0x00018cdc8058  (<unknown module>)

Indirect leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x000103018354 in calloc+0x64 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x34354)
    #1 0x00018cf6fb04 in _malloc_type_calloc_outlined+0x64 (libsystem_malloc.dylib:arm64+0x1cb04)
    #2 0x00018cd7ab70 in _fetchInitializingClassList(bool)+0xb0 (libobjc.A.dylib:arm64+0xab70)
 #3 0x00018cd7a9b8 in _setThisThreadIsInitializingClass(objc_class*)+0x1c (libobjc.A.dylib:arm64+0xa9b8)
    #4 0x00018cd7a7d4 in initializeNonMetaClass+0x234 (libobjc.A.dylib:arm64+0xa7d4)
    #5 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #6 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #7 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #8 0x00018cd98a38 in initializeAndMaybeRelock(objc_class*, objc_object*, locker_mixin<lockdebug::lock_mixin<objc_lock_base_t>>&, bool)+0xa0 (libobjc.A.dylib:arm64+0x28a38)
    #9 0x00018cd79f94 in lookUpImpOrForward+0x12c (libobjc.A.dylib:arm64+0x9f94)
    #10 0x00018cd79b80 in _objc_msgSend_uncached+0x40 (libobjc.A.dylib:arm64+0x9b80)
    #11 0x00018ce4bd54 in _xpc_collect_images+0xc0 (libxpc.dylib:arm64+0x2d54)
    #12 0x00018ce4b1b0 in _libxpc_initializer+0x424 (libxpc.dylib:arm64+0x21b0)
 #13 0x00019ac0d634 in libSystem_initializer+0xfc (libSystem.B.dylib:arm64+0x1634)
    #14 0x00018cddfd50 in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x110 (dyld:arm64+0xfffffffffff57d50)
    #15 0x00018ce1e4cc in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x150 (dyld:arm64+0xfffffffffff964cc)
 #16 0x00018ce11c34 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x1ec (dyld:arm64+0xfffffffffff89c34)
 #17 0x00018cdc42d8  (<unknown module>)
    #18 0x00018ce10bc8 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xbc (dyld:arm64+0xfffffffffff88bc8)
 #19 0x00018ce1dfe0 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x200 (dyld:arm64+0xfffffffffff95fe0)
 #20 0x00018cddfbb0 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xac (dyld:arm64+0xfffffffffff57bb0)
    #21 0x00018cdeabe4 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x28 (dyld:arm64+0xfffffffffff62be4)
    #22 0x00018cdff8b4 in dyld4::APIs::runAllInitializersForMain()+0x50 (dyld:arm64+0xfffffffffff778b4)
    #23 0x00018cdc98c4  (<unknown module>)
    #24 0x00018cdc8bbc  (<unknown module>)
    #25 0x00018cdc8058  (<unknown module>)

Indirect leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x000103018354 in calloc+0x64 (libclang_rt.lsan_osx_dynamic.dylib:arm64+0x34354)
    #1 0x00018cf6fb04 in _malloc_type_calloc_outlined+0x64 (libsystem_malloc.dylib:arm64+0x1cb04)
    #2 0x00018cd7ab3c in _fetchInitializingClassList(bool)+0x7c (libobjc.A.dylib:arm64+0xab3c)
 #3 0x00018cd7a9b8 in _setThisThreadIsInitializingClass(objc_class*)+0x1c (libobjc.A.dylib:arm64+0xa9b8)
    #4 0x00018cd7a7d4 in initializeNonMetaClass+0x234 (libobjc.A.dylib:arm64+0xa7d4)
    #5 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #6 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #7 0x00018cd7a638 in initializeNonMetaClass+0x98 (libobjc.A.dylib:arm64+0xa638)
    #8 0x00018cd98a38 in initializeAndMaybeRelock(objc_class*, objc_object*, locker_mixin<lockdebug::lock_mixin<objc_lock_base_t>>&, bool)+0xa0 (libobjc.A.dylib:arm64+0x28a38)
    #9 0x00018cd79f94 in lookUpImpOrForward+0x12c (libobjc.A.dylib:arm64+0x9f94)
    #10 0x00018cd79b80 in _objc_msgSend_uncached+0x40 (libobjc.A.dylib:arm64+0x9b80)
    #11 0x00018ce4bd54 in _xpc_collect_images+0xc0 (libxpc.dylib:arm64+0x2d54)
    #12 0x00018ce4b1b0 in _libxpc_initializer+0x424 (libxpc.dylib:arm64+0x21b0)
 #13 0x00019ac0d634 in libSystem_initializer+0xfc (libSystem.B.dylib:arm64+0x1634)
    #14 0x00018cddfd50 in invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0x110 (dyld:arm64+0xfffffffffff57d50)
    #15 0x00018ce1e4cc in invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x150 (dyld:arm64+0xfffffffffff964cc)
 #16 0x00018ce11c34 in invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0x1ec (dyld:arm64+0xfffffffffff89c34)
 #17 0x00018cdc42d8  (<unknown module>)
    #18 0x00018ce10bc8 in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const+0xbc (dyld:arm64+0xfffffffffff88bc8)
 #19 0x00018ce1dfe0 in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const+0x200 (dyld:arm64+0xfffffffffff95fe0)
 #20 0x00018cddfbb0 in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const+0xac (dyld:arm64+0xfffffffffff57bb0)
    #21 0x00018cdeabe4 in dyld4::PrebuiltLoader::runInitializers(dyld4::RuntimeState&) const+0x28 (dyld:arm64+0xfffffffffff62be4)
    #22 0x00018cdff8b4 in dyld4::APIs::runAllInitializersForMain()+0x50 (dyld:arm64+0xfffffffffff778b4)
    #23 0x00018cdc98c4  (<unknown module>)
    #24 0x00018cdc8bbc  (<unknown module>)
    #25 0x00018cdc8058  (<unknown module>)

SUMMARY: LeakSanitizer: 120 byte(s) leaked in 3 allocation(s).
```

Same for `clang -fsanitize=address foo.c && ASAN_OPTIONS=detect_leaks=1 ./a.out`.

</p>
</details> 

Clang version:
```
Homebrew clang version 19.1.3
Target: arm64-apple-darwin24.1.0
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/llvm/19.1.3/bin
Configuration file: /opt/homebrew/etc/clang/arm64-apple-darwin24.cfg
```

I'm using the Clang from Homebrew here, because Apple's bundled Clang does not have LeakSanitizer enabled. The problem also reproduces with the Clang from Nixpkgs, and with `rustc`.

Do tell me if there's something else I can do to help resolve this!

Originally reported in https://github.com/rust-lang/rust/issues/121624.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsW81u4zgSfhrmQrQhkbItH3JwfowN0OkMkp4F9mTwp2RxQpEGSSVxP_2ClBzLdradGewOdgYOgrREkfVVFYtFfo0i816tDMAlGl-h8c0Fa0Nt3WXDpG9Cc8Gt3FxetUpLZVaYGYlda0z3vMFrZ1eONfhVhRp_Bfb8xIwK6gc4bF3XOpfSgffvHxCZeowmmYQAIiw1sGeP6E2OJhn2tX31mOHYiJXBoQbsNz5Ag7XijrlNHKkVt_w3MZqP5EYrjibZCGU3KJt3f-9wAB9A4lArH6Uw_KJcaJnGDRO1MoCZx6-gNSLXXae1s1xDg9MjeDAhjQtRER_isIcnnNPROI7o34rRNLmjfx2P8n0tAl42bLPEHDAzmImkgPK-ha1lD08YkTLUtl3V-A5L2_KAVUBkFmF4G7CSwLTeHHjW17bVEldKB3BYBWzbEGejtq9xoFdGQJIz9djYELGVNYxrwJV1Cbr14PbURfRaQmBKe0RvEb32bdMwt0H0dtFqjTkTz8ExAdiagcVRfx5jA5PiimQljbrTa0QWu_Hv8te7l-7vJOt-hTXeauhbSYFB1BYjQpSJvlcGkRKRGUbTK-wgtM7gDNErjKY3iBCM6C2urB0JvP-zk4fIwq4DIovaNsAdvL43aP3SILLgEWMhNDMr_KXyvacRvUmBmITvpI0QWbCRbUPX1D2SckyLDJHr7C2vCCk5E1nUuWFaW4HoHBtmLP5hY_RxZqQ1ILFsAQeLlWFcaRU28SXGn3sB_NJgv2YCDqbp5i__OzAk-Sw93T4-PjxGN-2Femzo8gRI3EBj3QZ3CWPgkxvlQIQuZ9gKTwnmmwCIlD5OgDI4x5b_BiJsm9KUsCiycrZBtJeTYobQDGdvWZblGc3yMqvKKKGfRXKVvU2yGPRa8RQtSxdG2jOztP5tKTeGNUr0WYnOmWsmRRpEi6yKIbwHlPdApagmFStFBFp2SMuwWcP22bZBKwNyH75Li32fDyBzwUpxCEneIeWUsapIkBUEUd9FjzOtfiizutbM-6_KR4dxa3VKSMmKHnsv-w5Bo8wdJiKUDgFnPDlz6SF8r5X_Xjtg8s4fQSNSRoSl6F7mW_xcnMSf8SM3F0MVpjLZrLaQ8M2aewisx73K3sgnrJzK4hBlPESZ0PIEyqw8CTKhR6ZM_gyQ6Z8BUu5AZiU7BJkbec82HB5BW_F8HA7XODVsV3VqiT3BLRv1pgyi1_FVAm9XcXnTeXx9_5YGpxbOPCxD2vFuEZmkbXcQ8Cw7ZRuJyh8aNxt4cFbNUsRpa59_Xd816we3sO6VuW455-RkTEcJR6kjG0LwMkvrKtnV-NUTGLlsjWCi7rNGcdKQKOQIZZehoOBy3KWLt7VYCqt1PLyphq2giwOxhXhbf5SOiBwfW0GG8nPeWdGJWO6iwXUmkOLnADnP9lJPvs09MyYyOaHdNCj-1CXOQ_nVdiK676Orj3LqhB4bMcgvspLjrAvll7jDKGtw1RrRPViHeYy62EFutCy60PxqmUw7HaLzShk5N_KxNXOt73YaxpQ4GPLYmqAaeAos7nOTuKfFM1TolMzTTMTue8pXu5_xVI6PZ3uXwiCHQohPG0I7re6ZqB_mhunNj3d7rLtlg80l-rq8UWxlrA9K-H7N_VzIP-8jhbi25gVcPPD2pqaRL1bJaG1rEomRWJl4fu70W66tMiFi9h37kfMDh41POmw2KYTYj67JwFu5oMUf8tZCadjz1BOkUYiUW8v-85C-752p7J5Pugy2_XfygTv2rAdxyvpyJuj-tp4PNglREFnGCCoRvW7Ns7GvBjdWtlHP26MoKwd-y7go_0_dwk97peSi3PfKbGCbrCD7mywQkp1eIOMK9tMvyYZ5kfPsf5z22MkJG085P8p6ZLfHSWAcigM1f3EQCW4Yquta8weVJOUpJSeEw9EeQwbn9qoq-aGS81_u_LtqBy5cWHf_TqET2ul0N52W_FiJwVlezEpRfHrNk8EWKUrOxedHjocjs_En8kz_vy9G7rNC-t9khbQ7CokBKyz-ECukHxyKhqyQZ8URKxQfscLi06yQZ8czOzzx82n2-1ghP3m2jDLPrPDMCs-s8MwKz6zwzAr_EofeMys8s8IzKzyzwjMr_BuzwnxyZoWfY4VU_D5WOD3NyjgVZ1Z4ZoVnVnhmhWdWeGaFf4lD75kVnlnhmRWeWeGZFf59WOHTr_f388d_fVh8mpNsjyFG4pgWBqZbatjlmvh1dFDXvAfCmq76Gk2yD-qMWVck39cxp1iY4PnT_Nvy4Zfvdw_fnhC9OSyYHxQiH1TAdyXY62HxNSKLXX03Hna-Ttq8gPPREnpYnN29_qMvnMZi2Bvns1E-ol2X78ytIESnpTj5wtZrDV8kc6_KkGKUj3pRHZWLswE69l5br962_NwHpjXIG5W8_1Hd9jVozdyudLtXoavh7gyyplKr1vWba5fsP5QFQWzLvqMrP1JbVKufzOodItMGt16ZVSqr73xZOdvgd4_V4CDtJSBY6wHPI0CqzeetkRpkP0pa6Mr1a_YCBxX_kKr35Qh_r-H9sgLT3mIHa2dlK8B3ty0OtPim3tbPKx_xmZFdFzTJXOuDOIyaG4sDaI0bwKqKglynprcNhDqaCNoDvsOCGSwtDhbXoNfYgbf6BdJNCkTyocgHp1bKpCsMDtbWhW7t1CGsUxIiC0QWKxXqlo-EjdMZNfvST0h8RmSR7kz4ONUkn5BidCEvqZzRGbuAy3xK82JajKflRX05Bjkti3LMKpIBSFmV44JVUkjKQIipvFCXJCNFnuc0G2czWo5oRSkby3FRwIxCRlGRQcOUHsXgGlm3ukjgl3k-ns3IhWYctN9elHGXsdcX3q48KjKtfPC7cUEFna7UfH2af0Pjm4MJrVh0ZQz9oF52lyouWqcvf-KdPuYT7trZjtIOHNSp-XJJ_h0AAP___6OwKg">