C++ std::stable_sort crashes on iOS 12

Xcode 15 creates a binary that causes a crash on iOS 12 when I use C++ std::stable_sort. The following code works on iOS 17 but causes a crash on iOS 12. I remember that the earlier Xcode had no problem. It is no problem when I change "std::stable_sort" to "std::sort".

FB13430187

//
//  Tests.cpp
//

#include <tuple>
#include <vector>
#include <algorithm>
#include <iostream>

extern "C" {

void execute_tests(void)
{
    using T = std::tuple<size_t, uint64_t *>;
    std::vector<T> vector = { {7, nullptr}, {4, nullptr}, {9, nullptr} };
    std::stable_sort(vector.begin(), vector.end(), [](const T& a, const T& b){
        return std::get<0>(a) < std::get<0>(b);
    });
    for (const T& item : vector) {
        std::cout << std::get<0>(item) << std::endl;
    }
}

}

Answered by galad87 in 773517022

Try to switch back to the old linker. Xcode 15 ships with a new linker that might cause issues on older iOS versions (it definitely has issues on older macOS versions).

How exactly does it crash?

Xcode Version 15.0.1 (15A507), iPad mini 3, iOS 12.5.7 (16H81)

It crashes at an inline function.

template <class _Tp>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17
pair<_Tp*, ptrdiff_t>
get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT

crash at iPhoneOS17.0.sdk/usr/include/c++/v1/__memory/temprary_buffer.h:46

            __r.first = static_cast<_Tp*>(::operator new(
                __n * sizeof(_Tp), nothrow));

call back trace:

Thread 1 Queue : com.apple.main-thread (serial)
#0	0x0000000000000000 in 0x00000000 ()
#1	0x000000010096df10 in std::__1::pair<std::__1::tuple<unsigned long, unsigned long long*>*, long> std::__1::get_temporary_buffer[abi:v160006]<std::__1::tuple<unsigned long, unsigned long long*>>(long) at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.0.sdk/usr/include/c++/v1/__memory/temporary_buffer.h:46
#2	0x000000010096dd58 in void std::__1::__stable_sort_impl[abi:v160006]<std::__1::_ClassicAlgPolicy, std::__1::__wrap_iter<std::__1::tuple<unsigned long, unsigned long long*>*>, execute_tests::$_0>(std::__1::__wrap_iter<std::__1::tuple<unsigned long, unsigned long long*>*>, std::__1::__wrap_iter<std::__1::tuple<unsigned long, unsigned long long*>*>, execute_tests::$_0&) at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.0.sdk/usr/include/c++/v1/__algorithm/stable_sort.h:225
#3	0x000000010096c2a4 in void std::__1::stable_sort[abi:v160006]<std::__1::__wrap_iter<std::__1::tuple<unsigned long, unsigned long long*>*>, execute_tests::$_0>(std::__1::__wrap_iter<std::__1::tuple<unsigned long, unsigned long long*>*>, std::__1::__wrap_iter<std::__1::tuple<unsigned long, unsigned long long*>*>, execute_tests::$_0) at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.0.sdk/usr/include/c++/v1/__algorithm/stable_sort.h:236
#4	0x000000010096c110 in ::execute_tests() at /System/Volumes/Data/Developer/codes/test5/test5/Tests.cpp:19
#5	0x0000000100971b00 in -[AppDelegate application:didFinishLaunchingWithOptions:] at /System/Volumes/Data/Developer/codes/test5/test5/AppDelegate.m:21
#6	0x0000000256eca0f0 in -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] ()
#7	0x0000000256ecb854 in -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] ()
#8	0x0000000256ed0fe0 in -[UIApplication _runWithMainScene:transitionContext:completion:] ()
#9	0x00000002567942a4 in __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke ()
#10	0x000000025679c83c in +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] ()
#11	0x0000000256793f28 in -[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] ()
#12	0x0000000256794818 in -[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] ()
#13	0x0000000256792b64 in __82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke ()
#14	0x000000025679282c in -[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] ()
#15	0x000000025679736c in __125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke ()
#16	0x0000000256798150 in _performActionsWithDelayForTransitionContext ()
#17	0x0000000256797224 in -[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] ()
#18	0x000000025679bf24 in -[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] ()
#19	0x0000000256ecf5e8 in -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] ()
#20	0x0000000256acbe04 in -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] ()
#21	0x000000022d1d39fc in -[FBSSceneImpl _didCreateWithTransitionContext:completion:] ()
#22	0x000000022d1dd40c in __56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 ()
#23	0x000000022d1dcc14 in __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke ()
#24	0x0000000100cf0c78 in _dispatch_client_callout ()
#25	0x0000000100cf4840 in _dispatch_block_invoke_direct ()
#26	0x000000022d20e040 in __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ ()
#27	0x000000022d20dcdc in -[FBSSerialQueue _performNext] ()
#28	0x000000022d20e294 in -[FBSSerialQueue _performNextFromRunLoopSource] ()
#29	0x000000022a7e7f1c in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#30	0x000000022a7e7e9c in __CFRunLoopDoSource0 ()
#31	0x000000022a7e7784 in __CFRunLoopDoSources0 ()
#32	0x000000022a7e26c0 in __CFRunLoopRun ()
#33	0x000000022a7e1fb4 in CFRunLoopRunSpecific ()
#34	0x000000022c9e479c in GSEventRunModal ()
#35	0x0000000256ed2c38 in UIApplicationMain ()
#36	0x0000000100971ba8 in main at /System/Volumes/Data/Developer/codes/test5/test5/main.m:17

Error is that:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

Accepted Answer

Try to switch back to the old linker. Xcode 15 ships with a new linker that might cause issues on older iOS versions (it definitely has issues on older macOS versions).

@galad87 Thank you.

I added "-ld_classic" to other linker flags and the app doesn't crash on iOS 12.

Do we know if this is something that can be fixed in an iOS 12.x+1 release, or in an XCode 15.x+1 release?

I hope Xcode will be fixed. The ld_prime has the problem.

I've seen crashes, in the last week or so, with "new (std::nothrow) ClassName", with code built using Xcode 15.0.1, on iOS 12 and on an older version of MacOS (10.13, I think). The same binaries run fine on the latest iOS and MacOS. Removing the "(std::nothrow)" fixed the crash. The same code worked fine on all supported versions of MacOS and iOS when built with older Xcode.

Do we know if this is something that can be fixed in an iOS 12.x+1 release, or in an XCode 15.x+1 release?

It seems that binaries created with Xcode 15.1 work OK on iOS 12 without the need to specify -ld_classic.

I don't know if this is because the underlying problem has actually been fixed, or whether it now just uses ld_classic by default when the target is iOS 12.

C++ std::stable_sort crashes on iOS 12
 
 
Q