|Subject:||__NSCF** classes and libobjc2 dependency on C++ runtime|
|Date:||Tue, 04 Jun 2013 06:45:19 +0800|
|I did some research on how Apple implemented Objective-C exceptions and CoreFoundation on iOS (iOS 6.1.3 on iPhone 4S) and I found something that we can use.|
If you want me to test anything, please reply to this Email and I will test it for you. I have three devices to test: iOS 6.1.3 on iPhone 4S (armv7) and iPad 2 (armv7), as well as OS X 10.8.3 on my MacBook Pro (x86-64 and i386 both). I may also be able to borrow an iPad 4 for testing (iOS 6.1.2, armv7s)
1) Apple's libobjc depend on LLVM's libc++abi (in Linux, it should be libsupc++). Not only Apple did that to allow proper Objective-C++, but also something more.
When an Objective-C exception is triggered and not caught in Objective-C code, it will be raised as a C++ exception. This happens no matter if your code have C++ or not. Here is an crash log explaining this: (MobileDeuterium is the app I wrote. It have zero C++ in it.)
Incident Identifier: 3B2E3282-1537-4261-A77A-7931E8898F06
CrashReporter Key: 821361952184b8795bbbd7dd4b9db7b36d3a208a
Hardware Model: iPhone4,1
Process: MobileDeuterium 
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd 
Date/Time: 2013-05-26 08:45:19.713 +0800
OS Version: iOS 6.1.2 (10B146)
Report Version: 104
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Crashed Thread: 4
--- Lines truncated ---
Thread 4 name: Dispatch queue: com.apple.root.default-priority
Thread 4 Crashed:
0 libsystem_kernel.dylib 0x39c5e350 __pthread_kill + 8
1 libsystem_c.dylib 0x39bd511e pthread_kill + 54
2 libsystem_c.dylib 0x39c1196e abort + 90
3 libc++abi.dylib 0x391afd4a abort_message + 70
4 libc++abi.dylib 0x391acff4 default_terminate() + 20
5 libobjc.A.dylib 0x39760a74 _objc_terminate() + 144
6 libc++abi.dylib 0x391ad078 safe_handler_caller(void (*)()) + 76
7 libc++abi.dylib 0x391ad110 std::terminate() + 16
8 libc++abi.dylib 0x391ae50e __cxa_throw + 118
9 libobjc.A.dylib 0x397609ba objc_exception_throw + 90
10 CoreFoundation 0x31a46e02 -[NSObject(NSObject) doesNotRecognizeSelector:] + 166
11 CoreFoundation 0x31a4552c ___forwarding___ + 388
12 CoreFoundation 0x3199cf64 _CF_forwarding_prep_0 + 20
13 MobileDeuterium 0x0009ba36 0x97000 + 18998
14 libdispatch.dylib 0x39b7811c _dispatch_call_block_and_release + 8
15 libdispatch.dylib 0x39b7c95c _dispatch_root_queue_drain + 248
16 libdispatch.dylib 0x39b7cabc _dispatch_worker_thread2 + 80
17 libsystem_c.dylib 0x39baca0e _pthread_wqthread + 358
18 libsystem_c.dylib 0x39bac8a0 start_wqthread + 4
--- Lines truncated ---
Note: iPhone4,1 is the internal identifier of iPhone 4S.
2) Toll-Free Bridging is a cross-effort of both Foundation and CoreFoundation.
Try compile this code on OS X:
CFStringRef string = CFSTR("hello, world");
NSString *string_objc = (__bridge NSStirng *)string;
NSLog("Class: %@", NSStringFromClass([string_objc class]));
To compile: xcrun clang test.m -o test -framework Foundation -framework CoreFoundation -Wall -fobjc-arc
The output will be: "Class: __NSCFString" and one explanation of that: it is a CoreFoundation object toll-free bridged over into Foundation.
I saw this in my original ohttpd (on OS X) so here is my guess on how that worked:
1) All CoreFoundation objects have a complete Objective-C object structure, and its isa pointer is assigned to its Objective-C companion class. Given that Apple does not put retain counts in the object itself, this structure is only an isa pointer.
2) All CoreFoundation objects have a more or less functional Objective-C companion class.
3) For toll-free bridged objects, this companion class is a subclass of its public class cluster and have at least all important methods overridden with glue code that call into CoreFoundation functions.
4) For non-toll-free bridged objects, this companion class is a subclass of NSObject or NSProxy and implements only memory management methods.
5) CFRetain and CFRelease are stubs that call -[id<NSObject> retain] and -[id<NSObject> release]. CoreFoundation does not manage its memory directly using its own functions. Instead, all clean-ups are done by implementing a -[id<NSObject> dealloc] method in its companion Objective-C class.
6) When a Foundation object is passed into a CoreFoundation function as a parameter and the object is not subject to changes in the procedure, it is converted into its CoreFoundation counterpart, probably using -[id<NSCopying> copy] method.
7) When a Foundation object is passed into a CoreFoundation function as a parameter that will change the object itself, the function will call corresponding Foundation method(s) directly or via other CoreFoundation functions.
Description: Message signed with OpenPGP using GPGMail
|[Prev in Thread]||Current Thread||[Next in Thread]|