How to disable/override __builtin_operator_new/delete?


I’m trying to get my own global operator new/delete calls working that my memory manager plugs into.

This code is working fine on MacOS (clang) and Windows (Visual Studio), but on iOS I have a third party library (lohmann json) returning a std::string object which appears to have been allocated through my ::operator new function (I.e., my memory manager) but is being deleted through __builtin_operator_delete. Which just results in a crash almost immediately after the app starts.

So how do I disable these particular builtin functions?


There is no way to disable __builtin_operator_new/delete or prevent libc++
from using it.

I would be interested to get some more details about your particular case.
Ideally a reproducer
I could play with. Or at least provide some sort of stack trace and error

I'm not too familiar with the optimization aspects of
__builtin_operator_new/delete, but the behavior
you're observing sounds like a bug. Either in LLVM/Clang/libc++ or within
your build. My suspicion
is that an ODR violation is involved.


Hi Eric,

I’m trying to find the time to figure out a repo case for you to take a look at. Just got some xcode shenanigans to figure out. :slight_smile:

Our set up is as follows:

Static lib written in C++. Our memory manager exists in here.
Framework (shared library) with mixed Swift and C++ code. The global new/delete operators are compiled here, and the static lib is linked in as well.
App written in Swift.

As far as the callstack is concerned, it’s basically this:

#0 __pthread_kill ()
#1 pthread_kill$VARIANT$mp ()
#2 abort ()
#3 free ()
#4 std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >::~basic_string()

#5 The following five stack frames are in our C++ code…

#10 These four frames are Swift code in our framework…


#14 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:]
#15 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:]
#16 -[UIApplication _runWithMainScene:transitionContext:completion:]
#17 __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke
#18 +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:]
#19 -[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]
#20 -[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:]
#21 __82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke
#22 -[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]
#23 __125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke
#24 _performActionsWithDelayForTransitionContext
#25 -[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]
#26 -[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:]
#27 -[UIApplication workspace:didCreateScene:withTransitionContext:completion:]
#28 -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:]
#29 -[FBSSceneImpl _didCreateWithTransitionContext:completion:]
#30 __56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2
#31 _dispatch_client_callout
#32 _dispatch_block_invoke_direct
#34 -[FBSSerialQueue _performNext]
#35 -[FBSSerialQueue _performNextFromRunLoopSource]
#37 __CFRunLoopDoSource0
#38 __CFRunLoopDoSources0
#39 __CFRunLoopRun
#40 CFRunLoopRunSpecific
#41 GSEventRunModal
#42 UIApplicationMain
#43 main
#44 start

Nothing overly interesting to look at. As I mentioned before, this happens during application initialisation.

The output window in xcode simply has the following message:

malloc: *** error for objectt 0x1051bc0c0: pointer being freed was not allocated

Which is partially correct. It’s a 176 byte memory block allocated by my small block allocator. (I just managed to track it down.)

I don’t think the optimiser has anything to do with this. This is happening in debug builds.

It’s smells like a compiler bug to me. As I mentioned, the same code works fine on both MacOS, Windows, and the iOS simulator (which basically will compile to x86), so I would presume it’s ARM specific - but that’s merely a guess by me here.


So it seems this was due to including the source file that contains operator new and delete in the framework instead of the app.

Moving that file into the app layer appears to have solved the problem.

This comment here, ultimately provided me with the information I needed: