I think I found a bug in the Objective-C++ compiler, linker, or runtime. Here’s the scenario:
We have a macOS app written in Swift.
To control hardware from a 3rd party manufacturer, we use a couple SDKs provided by the manufacturer.
The SDKs use dynamically loaded libraries and the interface is defined in C++ headers.
To bridge between our Swift code and the C++ APIs we have a private Cocoapod that wraps the 3rd party interface with Objective-C++ classes.
The two SDKs each provide an interface for discovering attached devices using a callback class that the programmer provides. By accident we named both callback implementations DiscoveryCallback, but this was not a compiler error because neither class was publicly declared, and each was defined in the .mm file where it was used.
However, the problem we’re seeing is this:
We want to discover Videohub devices, so we register a new instance of DiscoveryCallback (defined in the same .mm file as this code) with the Videohub SDK.
A Videohub device is connected and the SDK calls a method on our callback.
Surprise! The callback we registered in step 1 was actually the one intended for Decklink devices, defined in a completely different .mm file.
This violates all sorts of assumptions and our app quickly crashes.
The funny thing is, the two implementations of DiscoveryCallback have completely different method names. The Videohub SDK is supposed to be calling NewVideohubDevice, yet somehow it successfully calls DeckLinkDeviceArrived on an instance of a class it shouldn’t even know about.
So the compiler has checked that our intended DiscoveryCallback matches the protocol that the SDK expects, but at runtime the compiled code instantiates a completely different implementation of DiscoveryCallback and somehow doesn’t immediately fail; we still call a method on it that doesn’t even share a name with the intended target. I imagine at this point the method names are long forgotten and are just pointers in a table.
I don’t know if this is a bug in the compiler, the Objective-C++ runtime, or if this is just “working as designed” undefined behavior that I should have avoided by not giving two private classes the same name. I know it’s possible to use a private API simply by redeclaring it in my own code, and this seems related to that, but I feel like the compiler or linker should have warned me that I had two implementations of the same class, or if that is not an error, then the runtime should have instantiated the class that was privately defined in the same source file where it was used.
Obviously I can’t share our entire project; I’d like to provide some sample code that replicates the issue, but I don’t have time to do that right now. I’m posting this to see if other developers have had a similar experience.
Objective-C Runtime
RSS for tagThe Objective-C runtime is a runtime library that supports the dynamic properties of the Objective-C language.
Posts under Objective-C Runtime tag
24 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I have created an app for iOS using React Native. I've gotten the app to a point where it works on the iPhone simulator via the Expo App. It even works when creating a build of the app to distribute using TestFlight. Now, I want to add Google Ads into the app. However, I've learned that Google Ads won't work via an Expo build. Instead one has to create a development build to test the ads in the app and see how they look.
I've also finally been able to compile a successful development build using eas (expo application services). When I install the app on the simulator and try to open it however, the app crashes almost immediately and I don't know why. I have tried deciphering the symbolicated crash report, but I have not been able to figure out what could be causing the error. It looks like it has something to do with the user interface.
Below is the thread where the app crashes:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x11324a14a __pthread_kill + 10
1 libsystem_pthread.dylib 0x1132abebd pthread_kill + 262
2 libsystem_c.dylib 0x7ff80016dd1c abort + 133
3 libc++abi.dylib 0x7ff8002c6d12 abort_message + 241
4 libc++abi.dylib 0x7ff8002b951a demangling_terminate_handler() + 266
5 libobjc.A.dylib 0x7ff800061fba _objc_terminate() + 96
6 libc++abi.dylib 0x7ff8002c616b std::__terminate(void (*)()) + 6
7 libc++abi.dylib 0x7ff8002c6126 std::terminate() + 54
8 libdispatch.dylib 0x7ff8001796ec _dispatch_client_callout + 28
9 libdispatch.dylib 0x7ff80017d1e2 _dispatch_block_invoke_direct + 508
10 FrontBoardServices 0x7ff807a8b3a7 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
11 FrontBoardServices 0x7ff807a8b281 -[FBSMainRunLoopSerialQueue _targetQueue_performNextIfPossible] + 188
12 FrontBoardServices 0x7ff807a8b3cf -[FBSMainRunLoopSerialQueue _performNextFromRunLoopSource] + 19
13 CoreFoundation 0x7ff800429ff3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
14 CoreFoundation 0x7ff800429f35 __CFRunLoopDoSource0 + 157
15 CoreFoundation 0x7ff800429732 __CFRunLoopDoSources0 + 215
16 CoreFoundation 0x7ff800423e67 __CFRunLoopRun + 919
17 CoreFoundation 0x7ff8004236ed CFRunLoopRunSpecific + 557
18 GraphicsServices 0x7ff8103ba08f GSEventRunModal + 137
19 UIKitCore 0x7ff805cdf6ee -[UIApplication _run] + 972
20 UIKitCore 0x7ff805ce416e UIApplicationMain + 123
21 LeftOff 0x10f870380 main + 96
22 dyld_sim 0x112d3a3e0 start_sim + 10
23 dyld 0x113d57366 start + 1942
I have been trying to solve this for some days now and could really use some help. I have tried changing versions of dependencies in my app too, with a focus on those that manage the UI. For example, I have changed packages such as react-native-ranimated, react-navigation/stack, react-native-gesture-handler, and react-native-screens to name a few. Nothing has worked so far. Please help.
if we define a property in the following way:
@property (atomic) NSString *latestObject;
Can we assume that the read write to that value is thread safe?
i.e the value will be correct.
Or it is better to write our own setter/getter with Locks?
I'm unable to run my app with ASAN enabled when targeting a physical iOS device. Simulator targets do work.
With Xcode 12 and an iPad mini 4 running iOS 14 beta 1 I get the following error during app launch
==750==ERROR: AddressSanitizer failed to allocate 0xffffffffff9fc000 (-6307840) bytes at address 2db624000 (errno: 22)
==750==ReserveShadowMemoryRange failed while trying to map 0xffffffffff9fc000 bytes. Perhaps you're using ulimit -v With Xcode 11.5 and an iPad Air 2 running OS 12.4.1 the error is
==2177==Unable to find a memory range after restricting VM.
==2177==AddressSanitizer CHECK failed: /BuildRoot/Library/Caches/com.apple.xbs/Sources/clangcompilerrt/clang-1103.0.32.62/compiler-rt/lib/asan/asanmac.cc:92 "((0 && "cannot place shadow after restricting vm")) != (0)" (0x0, 0x0)
<empty stack>==2177==AddressSanitizer CHECK failed: /BuildRoot/Library/Caches/com.apple.xbs/Sources/clangcompilerrt/clang-1103.0.32.62/compiler-rt/lib/asan/../sanitizercommon/sanitizermallocmac.inc:143 "((!asaninitisrunning)) != (0)" (0x0, 0x0)
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.
(lldb) thread info -s
thread #1: tid = 0x1076c2, 0x000000011531e984 libclangrt.asaniosdynamic.dylib`__asan::AsanDie() My coworker is able to use ASAN with the same App using iPad Pro 10.5, iPadOS 13.5.1, Xcode 11.5
Are there any configuration changes I need to make to be able to use ASAN on my devices?
Topic:
Developer Tools & Services
SubTopic:
Xcode
Tags:
Objective-C Runtime
Xcode
Developer Tools
Xcode Sanitizers and Runtime Issues