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.
General
RSS for tagDive into the world of programming languages used for app development.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I am getting an following error while compiling the
Fortran file with "gfortran TEST_1_fortran_only_fixed.f"
ld: unsupported tapi file type '!tapi-tbd' in YAML file '/Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk/usr/lib/libSystem.tbd' for architecture x86_64
collect2: error: ld returned 1 exit status
Please help me to solve this issue
I have a sandboxed app in /Applications.
I'm attempting to shoot a problem with LLDB, so I cd to /Applications/app-name/Contents/MacOS and do lldb programname.
However, once I fire it off with "r" it dies instantly with:
error: process exited with status -1 (lost connection)
Should this work? Should I try signing the lldb executable?
Thanks!