Objective-C Runtime

RSS for tag

The Objective-C runtime is a runtime library that supports the dynamic properties of the Objective-C language.

Posts under Objective-C Runtime tag

88 Posts

Post

Replies

Boosts

Views

Activity

xcode 15 dyld 报错
xcode :Version 15.0.1 (15A507) MACOS:13.6.1 (22G313) thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) frame #0: 0x0000000000000000 frame #1: 0x000000010482ec60 FUSTAKitOUTLINED_FUNCTION_3 + 580 frame #2: 0x0000000104430810 dyldImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 424 frame #3: 0x0000000104430bd8 dyldImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 52 frame #4: 0x000000010442b600 dyldImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 536 frame #5: 0x000000010442b56c dyldImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 388 frame #6: 0x0000000104429878 dyldImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 184 frame #7: 0x0000000104429940 dyldImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 92 frame #8: 0x000000010441a6d8 dylddyld::initializeMainExecutable() + 216 frame #9: 0x000000010441f928 dylddyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 5216 frame #10: 0x0000000104419208 dylddyldbootstrap::start(dyld3::MachOLoaded const*, int, char const**, dyld3::MachOLoaded const*, unsigned long*) + 396 frame #11: 0x0000000104419038 dyld`_dyld_start + 56 when I run a Test app(Just create with xcode Version 15.0.1 (15A507),without any extra code) depency FUSTAKit.framework packed by xcode Version 15.0.1 (15A507), i find this error。 but used xcode 14.2 pack FUSTA Kit.framework , everything is normal 。
2
0
1k
Dec ’23
Help with crash in objc_msgSend (no app code in stack trace)
Hello, I am attempting to track down a crash that isn't giving me a lot of information (crash log included below). Here is what I know so far: According to Apple documentation, a crash in objc_msgSend is due to a zombie object. So I have been trying to recreate the crash with zombies enabled, without success. The address of the object being messaged is 0x0000000000000010, a suspect value. It's always 0x10, across thousands of crash reports with slightly differing stack traces and circumstances. That makes me wonder if the runtime is trying to tell me something with that address, but I have been unable to find any documentation to that effect. We have internal analytics that suggest that the crash always happens after the user activates the system PIP video player, and usually also after backgrounding the app. It is also common (though not universal) that the crash occurs after the user has paused the video (and sometimes resumed it). This post is a bit of a Hail Mary; I'm hoping that maybe someone on here will see something I missed, because I have exhausted most of my own avenues of investigation. Many thanks for any help you can provide. 2023-11-30_07-16-00.4347_-0800-ffd5dc1a3d2ca628e1761ccfec5fe79f223d099e.crash
3
0
2.8k
Dec ’23
ArrayController is nil at Runtime after awakeFromNib
Hello, here is the block where arrayController is nil : { NSData * data; NSError * error; Class klass; if(_arrayController != nil) // nil ! { selected = [_arrayController selectedObjects]; arranged = [_arrayController arrangedObjects]; if([selected count] > 0) { _currentObject = [selected objectAtIndex:0]; if(_currentObject != nil) { data = [_currentObject valueForKey:kVrRoot]; klass = [NSMutableDictionary class]; _vrRoot = [NSKeyedUnarchiver unarchivedObjectOfClass:klass fromData:data error:&error]; }else { _vrRoot = [NSMutableDictionary new]; data = [NSKeyedArchiver archivedDataWithRootObject:_vrRoot requiringSecureCoding:YES error:&error]; } } } } I use this for years so I don't no what's wrong.
2
0
961
Nov ’23
iOS 17 weird behaviour when using categories
Hello, We have a legacy project that has a NSData category. This category is used to add a new method called "base64EncodedString" that we use for a custom base 64 encoding. Up until iOS 17, everything worked and we had no issue with it. This how we use it: NSString* text = @"This is the string we want to encode"; NSString* strArrRequests64 = [[text dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString]; We have a breakpoint in our implementation of base64EncodedString - (NSString *)base64EncodedString { size_t outputLength; char *outputBuffer = ....; NSString *result = [[[NSString alloc] initWithBytes:outputBuffer length:outputLength encoding:NSUTF8StringEncoding] autorelease]; free(outputBuffer); return result; } The strange thing is that we use this method for several calls in our app. In 80% of the cases it triggers the breakpoint and the encoding works as intended, but some calls do not and the encoding does not happen. We have checked the class of [text dataUsingEncoding:NSUTF8StringEncoding] and for all calls is "NSMutableConcreteData". This is a breaking change for iOS17 and it affects a lot of our clients. We have a solution for this particular case, but there are more categories inside our library which can be affected by this issue. Please advise.
3
0
887
Nov ’23
objc4-818.2 object_cxxDestructFromClass implementation
Below is the implementation of the object_cxxDestructFromClass method. the line below the for loop if (!cls->hasCxxDtor()) return; Some questions: If a subclass inherits a parent class, and one of the middle classes does not have a CxxDtor, but the parent class does, will there be any problems with the release of the instance? static void object_cxxDestructFromClass(id obj, Class cls) { void (*dtor)(id); // Call cls's dtor first, then superclasses's dtors. for ( ; cls; cls = cls->getSuperclass()) { if (!cls->hasCxxDtor()) return; dtor = (void(*)(id)) lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct); if (dtor != (void(*)(id))_objc_msgForward_impcache) { if (PrintCxxCtors) { _objc_inform("CXX: calling C++ destructors for class %s", cls->nameForLogging()); } (*dtor)(obj); } } }
0
0
548
Oct ’23
Xcode 15 Beta 6 objc @try @catch runtime error
I was migrating from Xcode 14 -> 15, and noticed that my code was failing with dyld[46534]: Symbol not found: _OBJC_CLASS_$_NSError I was able to debug the problem to some old objective c code, as documented in this thread: https://github.com/RonRadtke/react-native-blob-util/issues/273 The error seems to stem from this particular try catch block @try { // Some code } @catch(NSError *er) { // handle error } When I convert the code to catch an NSException instead, the runtime error goes away. Understandably, according to the apple docs, it should be throwing an NSException in the first place, but the documents do say Important: Although you can throw and catch objects other than NSException objects, the Cocoa frameworks themselves might only catch NSException objects for some conditions. So if you throw other types of objects, the Cocoa handlers for that exception might not run, with undefined results. (Conversely, non-NSException objects that you throw could be caught by some Cocoa handlers.) For these reasons, it is recommended that you throw NSException objects only, while being prepared to catch exception objects of all types. So it seems like this should not have produced a runtime error. I wanted to flag this in case the underlying code behind the @try @catch changed unintentionally.
4
0
2.6k
Oct ’23
Memory management between Objective-C Core WLAN Functions called from Go lang
Hi Experts, I am working on a application where I am calling Objective-C Core WLAN API from golang with below code, darwin_lib.m void ConnectWiFi(char * cInterfacename, char * cSSID, char * cSecurity, char *cSubsecurity, char * cPassphrase, char * cOnexuser, char * cOnexpass) { @autoreleasepool { NSString * interfacename = [[NSString alloc] initWithUTF8String:cInterfacename]; NSString * ssid = [[NSString alloc] initWithUTF8String:cSSID]; NSString * security = [[NSString alloc] initWithUTF8String:cSecurity]; NSString * subsecurity = [[NSString alloc] initWithUTF8String:cSubsecurity]; NSString * passphrase = [[NSString alloc] initWithUTF8String:cPassphrase]; NSString * onexuser = [[NSString alloc] initWithUTF8String:cOnexuser]; NSString * onexpass = [[NSString alloc] initWithUTF8String:cOnexpass]; NSError * connecterr = nil; CWWiFiClient * cwwificlient = [CWWiFiClient sharedWiFiClient]; CWInterface *a = [cwwificlient interfaceWithName:interfacename]; NSSet<CWNetwork *> * network = [a scanForNetworksWithName:ssid error:&connecterr]; **** some more code ***** BOOL result = [a associateToEnterpriseNetwork:network.anyObject identity:nil username:onexuser password:onexpass error:&connecterr]; main.go package main // #cgo CFLAGS: -x objective-c // #cgo LDFLAGS: -framework CoreWLAN // #cgo LDFLAGS: -framework Foundation // #include "clib.h" import "C" import "fmt" func main() { var status C.int = C.ConnectWiFi() time.Sleep(20) *** some more code and long running process *** } Now what I am trying to understand here from memory release point of view is, Is object created in C code will be freed once I reach time.Sleep(20) e.g cwwificlient a spcifically to Core WLAN side or do I have to call release specifically on object? I tried calling release on cwwificlient and program is crashing on second execution, not sure why it would crash on only second execution, why not first time itself? I tried calling release on a and program is not crashing. Do I have to free all the Core WLAN related object myself or autoreleasepool will take care of it? As whole code is inside autoreleasepool, will all the objects be released on it's own even though function is being called from go code? As go's garbage collector has no idea how many objects C code created so go's garbage collector won't be of any help here Is autoreleasepool, can also take care of releasing any alloc object e.g ssid created inside C code ?
3
0
1.1k
Aug ’23
iOS 17 Beta app crash when using [obj valueForKey:@"copy"]
I ran across the following crash while using one of our apps. The app crashes since the recent iOS 17 beta builds. The code crashes when using valueForKey on an NSArray with objects that implement NSCopying. like: [@[[Sample new]] valueForKey:@"copy"]; or: [[Sample new] valueForKey:@"copy"]; header: @interface Sample : NSObject<NSCopying> - (Sample *)copy; - (Sample *)copyWithZone:(nullable NSZone *)zone; @end implementation: @implementation Sample - (Sample *)copy { return [super copy]; } - (Sample *)copyWithZone:(nullable NSZone *)zone { return self; } @end Any idea why this might be happening? I have created a feedback too: FB12819891
4
0
1.9k
Aug ’23
iOS 16.0 _cache_getImp crash due to bad access
After the user upgrades to iOS16, our app receives a few crash reports attempted to dereference garbage pointer on iOS16. These issues only happen on iOS16. Here we provide some typical cases. It may be a system bug! Case A 0 libobjc.A.dylib _cache_getImp 1 libobjc.A.dylib _class_respondsToSelector_inst 2 Foundation __NSDescriptionWithStringProxyFunc 3 CoreFoundation ___CFStringAppendFormatCore 4 CoreFoundation __CFStringCreateWithFormatAndArgumentsReturningMetadata 5 CoreFoundation __CFStringCreateWithFormatAndArgumentsAux2 6 Foundation +[NSString stringWithFormat:] Case B 0 libobjc.A.dylib _cache_getImp 1 libobjc.A.dylib _object_getMethodImplementation 2 CoreFoundation __NSIsNSString 3 CoreFoundation -[NSTaggedPointerString isEqual:] 4 CoreFoundation -[__NSDictionaryM objectForKey:]
3
0
2.6k
May ’23
Objective-C copy properties
When I have a property like this: @property (nonatomic, readonly, copy) NSURL *sourceURL; And then I call: NSURL *url = self.sourceURL; Assuming that ARC is disabled, to ensure this object does not leak, must I manually release url? If so, how come I don't have to with: NSURL *url = [NSURL URLWithString:@"http://www.apple.com"]; NSURL *absURL = url.absoluteURL; Despite the absoluteString property also being readonly and copy: As per Apple: @property(nullable, readonly, copy) NSURL *absoluteURL;
2
0
1.8k
Apr ’23
Objective-C Memory Management for Swift Programmers
If you’re new to Apple platforms (welcome!) then you may encounter memory management terms that don’t fit into the Swift world view of strong and weak references. This post is my attempt to explain that terminology from a historical perspective. If you have a question about this stuff, please start a new thread with the Objective-C Runtime tag and I’ll try to respond there. ps This is written from an Apple perspective. Objective-C had a long history prior to Apple’s acquisition of NeXT. I wasn’t part of that story, so I’m not going to attempt to summarise it here. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Objective-C Memory Management for Swift Programmers In the beginning there was manual retain/release (MRR). Here’s a snippet: 1 - (void)printWaffleWithVarnish:(NSString *)varnish { 2 NSMutableString * waffle = [[NSMutableString alloc] init]; 3 [waffle appendString:@"waffle "]; 4 [waffle appendString:varnish]; 5 … print waffle … 6 [waffle release]; 7 } Yes, this is weird Objective-C syntax but lemme walk you through it: Line 1 defines a method called -printWaffleWithVarnish: that takes a single string parameter, varnish. Line 2 allocates a waffle mutable string. This alloc/init sequence returns an object with a +1 reference count. Lines 3 through 5 work with that. Line 6 releases the reference to it. This balances the +1 reference acquired in line 2. This model has one really nice property, namely that all the reasoning is local: The person implementing -printWaffleWithVarnish: doesn’t have to worry about the memory management for varnish. It’s the caller’s responsibility to make sure that it’s allocated before calling the method and deallocated after. The person calling -printWaffleWithVarnish: doesn’t have to worry about the memory management within that method. So, you can look at a method in isolation and know whether the memory management is correct. Enter Autorelease The above is fine but what do you do if you want a method that returns an object? You could always require methods to return objects with a +1 reference count, but that’s a hassle and, worse yet, it undermines the local reasoning property. To know whether the memory management is correct you have to look at both the method and its callers. The solution here is autorelease. Consider this method: 1 - (NSString *)waffleWithVarnish:(NSString *)varnish { 2 NSMutableString * waffle = [[NSMutableString alloc] init]; 3 [waffle appendString:@"waffle "]; 4 [waffle appendString:varnish]; 5 return [waffle autorelease]; 6 } The method definition on line 1 indicates that this returns a string with a +0 reference count. But… but… but… how is that possible? Well, the -autorelease on line 5 is the secret. It tells the runtime to add the object to the autorelease pool. At some point in the future the runtime will drain the pool. In the meantime, however, the person who called -waffleWithVarnish: is free to use the object. And if they want to hold on to the object for a long period of time, they can retain it themselves. This design has a number of nice features: It maintains the local reasoning property, and it’s easy for both the method’s implementer and the method’s caller. Note You can think of the autorelease pool as a giant array. When you call -autorelease, it adds the object to the array (without incrementing the retain count). When you drain the pool, it empties the array, releasing all the references as it goes. Back in the day the autorelease pool implementation was actually that simple. On modern systems it’s much more complex, with the benefit that it’s also much faster. So, when does this pool drain? Well, Objective-C’s bread and butter is GUI frameworks, and in a GUI framework there’s an obvious place to drain the pool, namely the event loop. Every time your app returns back to the event loop, the runtime drains the pool. Manually Draining the Pool This memory management model is good, but it’s not perfect. This code illustrates a common gotcha: NSArray * varnishes = … a very large array of varnishes … for (NSString * varnish in varnishes) { NSString * waffle = [waffleFactory waffleWithVarnish:varnish]; … work with the waffle … } Every time it calls -waffleWithVarnish:, the returned object ends up in the autorelease pool. If there are a lot of varnishes to apply, there can be a lot of objects in the pool. Those objects aren’t leaked — they’ll eventually be released when the pool drains — but they do increase the peak memory consumption of your code. The solution is to add a local autorelease pool: NSArray * varnishes = … a very large array of varnishes … for (NSString * varnish in varnishes) { @autoreleasepool { NSString * waffle = [waffleFactory waffleWithVarnish:varnish]; … work with the waffle … } } This drains the pool each time around the loop, avoiding any build up. These autorelease pools form a stack. The @autoreleasepool { } construct pushes a pool on to the stack, runs the code inside the curly brackets, then pops the pool off the top of the stack and drains it. When you autorelease an object, it’s always added to the pool on top of the stack. The @autoreleasepool { } construct arrived relatively late in the Objective-C story. Before that folks managed the autorelease pool stack with the NSAutoreleasePool type. This use of autorelease pools inside tight loops is one reason why it’s really important that the implementation be fast. Historically that wasn’t the case, and so you might see code that attempts to amortise the cost of pushing and popping the pool by unrolling the loop. Thank goodness we don’t have to do that any more (-: Modern Objective-C The local reasoning property of MRR makes it feasible to create a tool to check that the code is managing memory correctly. In Xcode 3.2 Apple added the static analyser which, amongst other things, can detect the most common bugs in MRR code. The success of the static analyser prompted Apple to introduce automatic reference counting (ARC) in Xcode 4.2. In this model the compiler adds the necessary memory management calls for you. Enter Swift, Stage Left So far, so Objective-C. It seems like none of the above is relevant to Swift programmers but it turns out that’s not the case. Imagine a Swift program like this: let varnishes: [String] = … a very large array of varnishes … for varnish in varnishes { let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } If the waffle factory is implemented in Objective-C, this can result in objects building up inside the autorelease pool. You solve this problem in Swift the same way you do in Objective-C, by adding an autorelease pool within the loop: let varnishes: [String] = … a very large array of varnishes … for varnish in varnishes { autoreleasepool { let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } } Swift itself does not use the autorelease pool. This only happens when you interact with Objective-C. Occasionally I see this bite folks bringing code from other platforms to an Apple platform. For example, if you have code that calls FileHandle in a tight loop, it won’t need an autoreleasepool(_:) call on Linux but it will on macOS. Threads Every thread has its own stack of autorelease pools. This makes sense when you think about it. If you’re running the above code on a secondary thread you don’t want your objects being released when the main thread returns to its event loop. Back in the day you had to set this up manually for secondary threads (the GUI framework would set it up for the main thread). If you didn’t, your thread would run with an empty autorelease pool stack and any objects you autoreleased ended up being leaked! At some point (macOS 10.7?) the system started creating an autorelease pool stack for every new thread. However, there’s still a gotcha here. Consider this code: func nextVarnish() -> String { … read varnish from the network … } Thread.detachNewThread { let waffleFactory = WaffleFactory() while true { let varnish = nextVarnish() let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } } The thread never terminates and so the autorelease pool never drains. This is what we call abandoned memory. It’s not a leak, because the process still has a reference to the objects in the pool and could theoretically release them, but that never happens in practice. The fix is to add an autorelease pool: Thread.detachNewThread { let waffleFactory = WaffleFactory() while true { autoreleasepool { let varnish = nextVarnish() let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } } } Dispatch Originally Dispatch knew nothing about autorelease pools. This meant that any work item you ran on a queue, other than the main queue, needed to set up and drain an autorelease pool. Without this it would leak. Yikes! This got worse when we added a default autorelease pool to every thread. This included the worker threads used by Dispatch. Now autoreleased objects wouldn’t leak, but rather build up in the worker thread’s autorelease pool. These would only be released when Dispatch terminated the worker thread, which in many cases never happened. Double yikes! This was fixed in macOS 10.12, where Dispatch finally got some autorelease pool smarts. There is now a pool associated with each queue and you can customise the frequency that it drains use an AutoreleaseFrequency value. Crashing Out of the Pool As a Swift programmer, your first encounter with the autorelease pool might be a crash. Consider this Swift function: 1 func simulateBadMRR() { 2 let b = (0...1023).map { _ in UInt8.random(in: 0...255) } 3 let d = NSData(bytes: b, length: b.count) 4 let du = Unmanaged.passUnretained(d) 5 print(du.takeUnretainedValue().count) 6 _ = du.autorelease() 7 } This simulates someone writing some bad MRR code. Line 4 creates a +0 reference to the NSData object and line 6 erroneously autoreleases that reference. If you call this function from Swift then, unless you’re very lucky, you won’t crash in the function itself. Remember that the function added its NSData reference to the autorelease pool, so the erroneous extra release doesn’t happen here. Rather, the function returns, and then your code returns, and eventually the thread gets back to a point where the system drains the autorelease pool. This finally performs the erroneous release and your program crashes. In the crash report you’ll see something like this: 0 libobjc.A.dylib … objc_release + 42 1 libobjc.A.dylib … AutoreleasePoolPage::releaseUntil(objc_object**) + 168 2 libobjc.A.dylib … objc_autoreleasePoolPop + 227 3 CoreFoundation … _CFAutoreleasePoolPop + 22 4 Foundation … -[NSAutoreleasePool drain] + 133 5 AppKit … -[NSApplication run] + 636 6 AppKit … NSApplicationMain + 817 7 CrashingOutOfThePool … main + 9 (AppDelegate.swift:4) 8 dyld … start + 2432 This example is from an AppKit app, and so frame 5 is the NSApplication.run() method draining the autorelease pool. Frames 4 through 1 are autorelease pool gubbins, where frame 1 actually performs the erroneous release which triggers the crash in frame 0. Debugging over release bugs like this is hard because the source of the error, the extraneous autorelease in simulateBadMRR(), is far removed from the crash. Fortunately, Apple has your back here, in the form of the zombies feature. This does two things: It replaces deallocated objects with a zombie. This traps if anyone calls it, which makes crashes like this easy to reproduce. For example, in my test app I had a button wired up to the simulateBadMRR() code and the first time I clicked that button it didn’t crash. I had to click it twice to trigger the crash. With zombies enabled, it traps on the first click. In Instruments the Zombies template enables reference count tracking, so you get a backtrace of where the object was allocated and every time its reference count was modified. For more information about the zombies feature, see my Standard Memory Debugging Tools post. Revision History 2023-03-23 Added the Crashing Out of the Pool section. 2022-09-28 First posted.
0
0
4.7k
Mar ’23
Upgrde an old app to ventura with your Xcode 4.5 source.
Hello, can upgrade an old front-end app for mac ventura 13.0? I have the complete source write in cocoa xCode e object C. When try to export app the system tell me Build fail. Have 5 error in syntax of CGColours component and conversion. The source in question is avaible for free at this link. https://mnt.conts.it/winxound/downloads/WinXound_3_4_0_OSX_Sources_XCode_4_5_0.zip Thank’s anyway.
2
0
1.2k
Mar ’23
protocol_addMethodDescription problems
Hi, I'm wondering if anyone else has seen this (and hopefully found a workaround). I'm working on a bug in PyObjC (https://github.com/ronaldoussoren/pyobjc/issues/17) related to protocols and can reproduce this in pure (Objective-)C. PyObjC creates a protocol and populates the method descriptors using the Objective-C runtime API, e.g. objc_allocateProtocol and protocol_getMethodDescription. This appears to work unreliably when adding multiple methods using protocol_getMethodDescription when the selector name and/or type encoding argument to protocol_getMethodDescription are not static strings: When the arguments are not static strings I have trouble finding the method descriptor using protocol_getMethodDescription. The code fails intermittently when adding two methods (but still fairly often), and fails reliably for me when adding 3 methods. The PyObjC issue I mentioned earlier contains a full reproducer.
1
0
716
Feb ’23
[Big Sur] /usr/lib/libobjc.A.dylib: Cannot load Swift type information
We are having a problem when we try to assign a nil value to a @objc dynamic lazy property ... The log shows this: /usr/lib/libobjc.A.dylib: Cannot load Swift type information; failed to initialize ClangImporter: error: invalid Darwin version number: macosx11.0.0 error: invalid version number in '--target = x86_64-apple-macosx11.0.0' It usually occurs when we try to assign a nil value to a @objc dynamic lazy property. (only in Big Sur beta 5 or higher) In our tearDown() logic, we manually clear references. ... // Clear strong references to objects in other MOC's result = nil // declared property that stores some coredata objects. @objc dynamic lazy var result: Result? = {[weak self] in I found this observation in the release notes: https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11-beta-release-notes Known Issues ... New in macOS Big Sur 11 beta, the system ships with a built-in dynamic linker cache of all system-provided libraries. As part of this change, copies of dynamic libraries are no longer present on the filesystem. Code that attempts to check for dynamic library presence by looking for a file at a path or enumerating a directory will fail. Instead, check for library presence by attempting to dlopen () the path, which will correctly check for the library in the cache. (62986286) ... This problem causes an application crash. Is this a mistake? Will it be available in future versions? Will it get replaced by an alternative? Thx in advance! P.s. Out of curiosity, I didn't find the /usr/lib/libobjc.A.dylib library available in Big Sur anymore, but it is present in Catalina.
2
1
4.7k
Jan ’23
Retain count and memory management
I have prepared an example to easier describe what I am want to ask: @interface ViewController () @end @implementation ViewController {   UIColor *_color; } - (void)viewDidLoad {   [super viewDidLoad];       [self getStaticVC];       __block CFTypeRef test1;   __block CFTypeRef test2;   __block CFTypeRef test3;   @autoreleasepool {     test1 = [self getVC];     test2 = [self getVC];     test3 = [self getVC];           NSLog(@"Test1: %lld", CFGetRetainCount(test1));     NSLog(@"Test2: %lld", CFGetRetainCount(test2));     NSLog(@"Test3: %lld", CFGetRetainCount(test3));   } } - (UIViewController *)getStaticVC {   static UIViewController *vc;   if (!vc) {     vc = [UIViewController new];   }   return vc; } - (CFTypeRef)getVC {   return (__bridge CFTypeRef)[self getStaticVC]; } @end For this code above, if I will run it, it will print always that retain count is 4, but if I will change implementation of the method getVC to this: - (CFTypeRef)getVC { UIViewController *temp = [self getStaticVC];   return (__bridge CFTypeRef)temp; } Code will always print retain count as 1. My guess it is related to reference storage qualifier that is assigned to returned values from this methods. For value returned from getVC there are no storage qualifier, cos it is a void *, so I guess when we assigning to UIViewController *temp it likely mean that we are getting __strong local variable that is deallocated right after getVC finish, but for my first example, it seems like getVC return an __autoreleasing reference, otherwise I have no idea why reference count is growing ?
1
0
1.4k
Jan ’23
wkwebview.navigationdelegate is still nil after assigned delegate
I assign its navigationDelegate in my 'CustomWebView' init function, the init function is called in the viewDidLoad function and the 'CustomWebView' implements the WKNavigationDelegate functions, objection_requires(NSStringFromSelector(@selector(configRepository))) - (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration configRepository:(SKYConfigRepository *)configRepository { self = [super init]; _configRepository = configRepository; if (self) { [[JSObjection defaultInjector] injectDependencies:self]; self.converterLink = [JSObjection defaultInjector][@protocol(UniversalLinkConverterProtocol)]; WKWebViewConfiguration *wkWebViewConfig = [self getWebViewConfigWithUpdatedUserAgent:configuration]; _wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:wkWebViewConfig]; _wkWebView.navigationDelegate = self; ... ... then when I debug the '_wkWebView.navigationDelegate' is nil the 'self' is not nil, and it implements the WKNavigationDelegate, {   WKWebView *_wkWebView;   SKYConfigRepository *_configRepository; }
3
0
1.8k
Dec ’22
xcode 15 dyld 报错
xcode :Version 15.0.1 (15A507) MACOS:13.6.1 (22G313) thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) frame #0: 0x0000000000000000 frame #1: 0x000000010482ec60 FUSTAKitOUTLINED_FUNCTION_3 + 580 frame #2: 0x0000000104430810 dyldImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 424 frame #3: 0x0000000104430bd8 dyldImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 52 frame #4: 0x000000010442b600 dyldImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 536 frame #5: 0x000000010442b56c dyldImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 388 frame #6: 0x0000000104429878 dyldImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 184 frame #7: 0x0000000104429940 dyldImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 92 frame #8: 0x000000010441a6d8 dylddyld::initializeMainExecutable() + 216 frame #9: 0x000000010441f928 dylddyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 5216 frame #10: 0x0000000104419208 dylddyldbootstrap::start(dyld3::MachOLoaded const*, int, char const**, dyld3::MachOLoaded const*, unsigned long*) + 396 frame #11: 0x0000000104419038 dyld`_dyld_start + 56 when I run a Test app(Just create with xcode Version 15.0.1 (15A507),without any extra code) depency FUSTAKit.framework packed by xcode Version 15.0.1 (15A507), i find this error。 but used xcode 14.2 pack FUSTA Kit.framework , everything is normal 。
Replies
2
Boosts
0
Views
1k
Activity
Dec ’23
Help with crash in objc_msgSend (no app code in stack trace)
Hello, I am attempting to track down a crash that isn't giving me a lot of information (crash log included below). Here is what I know so far: According to Apple documentation, a crash in objc_msgSend is due to a zombie object. So I have been trying to recreate the crash with zombies enabled, without success. The address of the object being messaged is 0x0000000000000010, a suspect value. It's always 0x10, across thousands of crash reports with slightly differing stack traces and circumstances. That makes me wonder if the runtime is trying to tell me something with that address, but I have been unable to find any documentation to that effect. We have internal analytics that suggest that the crash always happens after the user activates the system PIP video player, and usually also after backgrounding the app. It is also common (though not universal) that the crash occurs after the user has paused the video (and sometimes resumed it). This post is a bit of a Hail Mary; I'm hoping that maybe someone on here will see something I missed, because I have exhausted most of my own avenues of investigation. Many thanks for any help you can provide. 2023-11-30_07-16-00.4347_-0800-ffd5dc1a3d2ca628e1761ccfec5fe79f223d099e.crash
Replies
3
Boosts
0
Views
2.8k
Activity
Dec ’23
ArrayController is nil at Runtime after awakeFromNib
Hello, here is the block where arrayController is nil : { NSData * data; NSError * error; Class klass; if(_arrayController != nil) // nil ! { selected = [_arrayController selectedObjects]; arranged = [_arrayController arrangedObjects]; if([selected count] &gt; 0) { _currentObject = [selected objectAtIndex:0]; if(_currentObject != nil) { data = [_currentObject valueForKey:kVrRoot]; klass = [NSMutableDictionary class]; _vrRoot = [NSKeyedUnarchiver unarchivedObjectOfClass:klass fromData:data error:&amp;error]; }else { _vrRoot = [NSMutableDictionary new]; data = [NSKeyedArchiver archivedDataWithRootObject:_vrRoot requiringSecureCoding:YES error:&amp;error]; } } } } I use this for years so I don't no what's wrong.
Replies
2
Boosts
0
Views
961
Activity
Nov ’23
What does it mean? "mixed ObjC ABI, somelibrary.a compiled without category class properties"
Is there any documentation about the Objective-C ABI changes that cause the above warning warning: mixed ObjC ABI, libSomeLib.a compiled without category class properties ? what are "category class properties"
Replies
10
Boosts
2
Views
3.6k
Activity
Nov ’23
iOS 17 weird behaviour when using categories
Hello, We have a legacy project that has a NSData category. This category is used to add a new method called "base64EncodedString" that we use for a custom base 64 encoding. Up until iOS 17, everything worked and we had no issue with it. This how we use it: NSString* text = @"This is the string we want to encode"; NSString* strArrRequests64 = [[text dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString]; We have a breakpoint in our implementation of base64EncodedString - (NSString *)base64EncodedString { size_t outputLength; char *outputBuffer = ....; NSString *result = [[[NSString alloc] initWithBytes:outputBuffer length:outputLength encoding:NSUTF8StringEncoding] autorelease]; free(outputBuffer); return result; } The strange thing is that we use this method for several calls in our app. In 80% of the cases it triggers the breakpoint and the encoding works as intended, but some calls do not and the encoding does not happen. We have checked the class of [text dataUsingEncoding:NSUTF8StringEncoding] and for all calls is "NSMutableConcreteData". This is a breaking change for iOS17 and it affects a lot of our clients. We have a solution for this particular case, but there are more categories inside our library which can be affected by this issue. Please advise.
Replies
3
Boosts
0
Views
887
Activity
Nov ’23
objc4-818.2 object_cxxDestructFromClass implementation
Below is the implementation of the object_cxxDestructFromClass method. the line below the for loop if (!cls->hasCxxDtor()) return; Some questions: If a subclass inherits a parent class, and one of the middle classes does not have a CxxDtor, but the parent class does, will there be any problems with the release of the instance? static void object_cxxDestructFromClass(id obj, Class cls) { void (*dtor)(id); // Call cls's dtor first, then superclasses's dtors. for ( ; cls; cls = cls->getSuperclass()) { if (!cls->hasCxxDtor()) return; dtor = (void(*)(id)) lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct); if (dtor != (void(*)(id))_objc_msgForward_impcache) { if (PrintCxxCtors) { _objc_inform("CXX: calling C++ destructors for class %s", cls->nameForLogging()); } (*dtor)(obj); } } }
Replies
0
Boosts
0
Views
548
Activity
Oct ’23
How can I get name of variable (it is an object) as string at runtime in Swift?
class Employee { func calculateSalary() { -> how can I print name of the variable call in this function? } } Example: let johnny = Employee() johnny.calculateSalary() -> It will print "johnny" in function calculateSalary()
Replies
3
Boosts
0
Views
1.3k
Activity
Oct ’23
Xcode 15 Beta 6 objc @try @catch runtime error
I was migrating from Xcode 14 -> 15, and noticed that my code was failing with dyld[46534]: Symbol not found: _OBJC_CLASS_$_NSError I was able to debug the problem to some old objective c code, as documented in this thread: https://github.com/RonRadtke/react-native-blob-util/issues/273 The error seems to stem from this particular try catch block @try { // Some code } @catch(NSError *er) { // handle error } When I convert the code to catch an NSException instead, the runtime error goes away. Understandably, according to the apple docs, it should be throwing an NSException in the first place, but the documents do say Important: Although you can throw and catch objects other than NSException objects, the Cocoa frameworks themselves might only catch NSException objects for some conditions. So if you throw other types of objects, the Cocoa handlers for that exception might not run, with undefined results. (Conversely, non-NSException objects that you throw could be caught by some Cocoa handlers.) For these reasons, it is recommended that you throw NSException objects only, while being prepared to catch exception objects of all types. So it seems like this should not have produced a runtime error. I wanted to flag this in case the underlying code behind the @try @catch changed unintentionally.
Replies
4
Boosts
0
Views
2.6k
Activity
Oct ’23
Memory management between Objective-C Core WLAN Functions called from Go lang
Hi Experts, I am working on a application where I am calling Objective-C Core WLAN API from golang with below code, darwin_lib.m void ConnectWiFi(char * cInterfacename, char * cSSID, char * cSecurity, char *cSubsecurity, char * cPassphrase, char * cOnexuser, char * cOnexpass) { @autoreleasepool { NSString * interfacename = [[NSString alloc] initWithUTF8String:cInterfacename]; NSString * ssid = [[NSString alloc] initWithUTF8String:cSSID]; NSString * security = [[NSString alloc] initWithUTF8String:cSecurity]; NSString * subsecurity = [[NSString alloc] initWithUTF8String:cSubsecurity]; NSString * passphrase = [[NSString alloc] initWithUTF8String:cPassphrase]; NSString * onexuser = [[NSString alloc] initWithUTF8String:cOnexuser]; NSString * onexpass = [[NSString alloc] initWithUTF8String:cOnexpass]; NSError * connecterr = nil; CWWiFiClient * cwwificlient = [CWWiFiClient sharedWiFiClient]; CWInterface *a = [cwwificlient interfaceWithName:interfacename]; NSSet<CWNetwork *> * network = [a scanForNetworksWithName:ssid error:&connecterr]; **** some more code ***** BOOL result = [a associateToEnterpriseNetwork:network.anyObject identity:nil username:onexuser password:onexpass error:&connecterr]; main.go package main // #cgo CFLAGS: -x objective-c // #cgo LDFLAGS: -framework CoreWLAN // #cgo LDFLAGS: -framework Foundation // #include "clib.h" import "C" import "fmt" func main() { var status C.int = C.ConnectWiFi() time.Sleep(20) *** some more code and long running process *** } Now what I am trying to understand here from memory release point of view is, Is object created in C code will be freed once I reach time.Sleep(20) e.g cwwificlient a spcifically to Core WLAN side or do I have to call release specifically on object? I tried calling release on cwwificlient and program is crashing on second execution, not sure why it would crash on only second execution, why not first time itself? I tried calling release on a and program is not crashing. Do I have to free all the Core WLAN related object myself or autoreleasepool will take care of it? As whole code is inside autoreleasepool, will all the objects be released on it's own even though function is being called from go code? As go's garbage collector has no idea how many objects C code created so go's garbage collector won't be of any help here Is autoreleasepool, can also take care of releasing any alloc object e.g ssid created inside C code ?
Replies
3
Boosts
0
Views
1.1k
Activity
Aug ’23
iOS 17 Beta app crash when using [obj valueForKey:@"copy"]
I ran across the following crash while using one of our apps. The app crashes since the recent iOS 17 beta builds. The code crashes when using valueForKey on an NSArray with objects that implement NSCopying. like: [@[[Sample new]] valueForKey:@"copy"]; or: [[Sample new] valueForKey:@"copy"]; header: @interface Sample : NSObject<NSCopying> - (Sample *)copy; - (Sample *)copyWithZone:(nullable NSZone *)zone; @end implementation: @implementation Sample - (Sample *)copy { return [super copy]; } - (Sample *)copyWithZone:(nullable NSZone *)zone { return self; } @end Any idea why this might be happening? I have created a feedback too: FB12819891
Replies
4
Boosts
0
Views
1.9k
Activity
Aug ’23
Crash from: ContextKitExtraction +[CKContextContentProviderUIScene _bestVisibleStringForView:usingExecutor:] + 948 (CKContextContentProviderUIScene.m:533)
Any ideas on how to root cause this? Started since iOS 15.x, affecting only small percentage of users. Apple crash report attached. Thanks! 2023-07-25_15-08-32.4590_-0400-444d5ea058bb103160c275742f01d7f130e02661.crash
Replies
2
Boosts
0
Views
1.1k
Activity
Jul ’23
iOS 16.0 _cache_getImp crash due to bad access
After the user upgrades to iOS16, our app receives a few crash reports attempted to dereference garbage pointer on iOS16. These issues only happen on iOS16. Here we provide some typical cases. It may be a system bug! Case A 0 libobjc.A.dylib _cache_getImp 1 libobjc.A.dylib _class_respondsToSelector_inst 2 Foundation __NSDescriptionWithStringProxyFunc 3 CoreFoundation ___CFStringAppendFormatCore 4 CoreFoundation __CFStringCreateWithFormatAndArgumentsReturningMetadata 5 CoreFoundation __CFStringCreateWithFormatAndArgumentsAux2 6 Foundation +[NSString stringWithFormat:] Case B 0 libobjc.A.dylib _cache_getImp 1 libobjc.A.dylib _object_getMethodImplementation 2 CoreFoundation __NSIsNSString 3 CoreFoundation -[NSTaggedPointerString isEqual:] 4 CoreFoundation -[__NSDictionaryM objectForKey:]
Replies
3
Boosts
0
Views
2.6k
Activity
May ’23
Objective-C copy properties
When I have a property like this: @property (nonatomic, readonly, copy) NSURL *sourceURL; And then I call: NSURL *url = self.sourceURL; Assuming that ARC is disabled, to ensure this object does not leak, must I manually release url? If so, how come I don't have to with: NSURL *url = [NSURL URLWithString:@"http://www.apple.com"]; NSURL *absURL = url.absoluteURL; Despite the absoluteString property also being readonly and copy: As per Apple: @property(nullable, readonly, copy) NSURL *absoluteURL;
Replies
2
Boosts
0
Views
1.8k
Activity
Apr ’23
Objective-C Memory Management for Swift Programmers
If you’re new to Apple platforms (welcome!) then you may encounter memory management terms that don’t fit into the Swift world view of strong and weak references. This post is my attempt to explain that terminology from a historical perspective. If you have a question about this stuff, please start a new thread with the Objective-C Runtime tag and I’ll try to respond there. ps This is written from an Apple perspective. Objective-C had a long history prior to Apple’s acquisition of NeXT. I wasn’t part of that story, so I’m not going to attempt to summarise it here. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Objective-C Memory Management for Swift Programmers In the beginning there was manual retain/release (MRR). Here’s a snippet: 1 - (void)printWaffleWithVarnish:(NSString *)varnish { 2 NSMutableString * waffle = [[NSMutableString alloc] init]; 3 [waffle appendString:@"waffle "]; 4 [waffle appendString:varnish]; 5 … print waffle … 6 [waffle release]; 7 } Yes, this is weird Objective-C syntax but lemme walk you through it: Line 1 defines a method called -printWaffleWithVarnish: that takes a single string parameter, varnish. Line 2 allocates a waffle mutable string. This alloc/init sequence returns an object with a +1 reference count. Lines 3 through 5 work with that. Line 6 releases the reference to it. This balances the +1 reference acquired in line 2. This model has one really nice property, namely that all the reasoning is local: The person implementing -printWaffleWithVarnish: doesn’t have to worry about the memory management for varnish. It’s the caller’s responsibility to make sure that it’s allocated before calling the method and deallocated after. The person calling -printWaffleWithVarnish: doesn’t have to worry about the memory management within that method. So, you can look at a method in isolation and know whether the memory management is correct. Enter Autorelease The above is fine but what do you do if you want a method that returns an object? You could always require methods to return objects with a +1 reference count, but that’s a hassle and, worse yet, it undermines the local reasoning property. To know whether the memory management is correct you have to look at both the method and its callers. The solution here is autorelease. Consider this method: 1 - (NSString *)waffleWithVarnish:(NSString *)varnish { 2 NSMutableString * waffle = [[NSMutableString alloc] init]; 3 [waffle appendString:@"waffle "]; 4 [waffle appendString:varnish]; 5 return [waffle autorelease]; 6 } The method definition on line 1 indicates that this returns a string with a +0 reference count. But… but… but… how is that possible? Well, the -autorelease on line 5 is the secret. It tells the runtime to add the object to the autorelease pool. At some point in the future the runtime will drain the pool. In the meantime, however, the person who called -waffleWithVarnish: is free to use the object. And if they want to hold on to the object for a long period of time, they can retain it themselves. This design has a number of nice features: It maintains the local reasoning property, and it’s easy for both the method’s implementer and the method’s caller. Note You can think of the autorelease pool as a giant array. When you call -autorelease, it adds the object to the array (without incrementing the retain count). When you drain the pool, it empties the array, releasing all the references as it goes. Back in the day the autorelease pool implementation was actually that simple. On modern systems it’s much more complex, with the benefit that it’s also much faster. So, when does this pool drain? Well, Objective-C’s bread and butter is GUI frameworks, and in a GUI framework there’s an obvious place to drain the pool, namely the event loop. Every time your app returns back to the event loop, the runtime drains the pool. Manually Draining the Pool This memory management model is good, but it’s not perfect. This code illustrates a common gotcha: NSArray * varnishes = … a very large array of varnishes … for (NSString * varnish in varnishes) { NSString * waffle = [waffleFactory waffleWithVarnish:varnish]; … work with the waffle … } Every time it calls -waffleWithVarnish:, the returned object ends up in the autorelease pool. If there are a lot of varnishes to apply, there can be a lot of objects in the pool. Those objects aren’t leaked — they’ll eventually be released when the pool drains — but they do increase the peak memory consumption of your code. The solution is to add a local autorelease pool: NSArray * varnishes = … a very large array of varnishes … for (NSString * varnish in varnishes) { @autoreleasepool { NSString * waffle = [waffleFactory waffleWithVarnish:varnish]; … work with the waffle … } } This drains the pool each time around the loop, avoiding any build up. These autorelease pools form a stack. The @autoreleasepool { } construct pushes a pool on to the stack, runs the code inside the curly brackets, then pops the pool off the top of the stack and drains it. When you autorelease an object, it’s always added to the pool on top of the stack. The @autoreleasepool { } construct arrived relatively late in the Objective-C story. Before that folks managed the autorelease pool stack with the NSAutoreleasePool type. This use of autorelease pools inside tight loops is one reason why it’s really important that the implementation be fast. Historically that wasn’t the case, and so you might see code that attempts to amortise the cost of pushing and popping the pool by unrolling the loop. Thank goodness we don’t have to do that any more (-: Modern Objective-C The local reasoning property of MRR makes it feasible to create a tool to check that the code is managing memory correctly. In Xcode 3.2 Apple added the static analyser which, amongst other things, can detect the most common bugs in MRR code. The success of the static analyser prompted Apple to introduce automatic reference counting (ARC) in Xcode 4.2. In this model the compiler adds the necessary memory management calls for you. Enter Swift, Stage Left So far, so Objective-C. It seems like none of the above is relevant to Swift programmers but it turns out that’s not the case. Imagine a Swift program like this: let varnishes: [String] = … a very large array of varnishes … for varnish in varnishes { let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } If the waffle factory is implemented in Objective-C, this can result in objects building up inside the autorelease pool. You solve this problem in Swift the same way you do in Objective-C, by adding an autorelease pool within the loop: let varnishes: [String] = … a very large array of varnishes … for varnish in varnishes { autoreleasepool { let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } } Swift itself does not use the autorelease pool. This only happens when you interact with Objective-C. Occasionally I see this bite folks bringing code from other platforms to an Apple platform. For example, if you have code that calls FileHandle in a tight loop, it won’t need an autoreleasepool(_:) call on Linux but it will on macOS. Threads Every thread has its own stack of autorelease pools. This makes sense when you think about it. If you’re running the above code on a secondary thread you don’t want your objects being released when the main thread returns to its event loop. Back in the day you had to set this up manually for secondary threads (the GUI framework would set it up for the main thread). If you didn’t, your thread would run with an empty autorelease pool stack and any objects you autoreleased ended up being leaked! At some point (macOS 10.7?) the system started creating an autorelease pool stack for every new thread. However, there’s still a gotcha here. Consider this code: func nextVarnish() -> String { … read varnish from the network … } Thread.detachNewThread { let waffleFactory = WaffleFactory() while true { let varnish = nextVarnish() let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } } The thread never terminates and so the autorelease pool never drains. This is what we call abandoned memory. It’s not a leak, because the process still has a reference to the objects in the pool and could theoretically release them, but that never happens in practice. The fix is to add an autorelease pool: Thread.detachNewThread { let waffleFactory = WaffleFactory() while true { autoreleasepool { let varnish = nextVarnish() let waffle = waffleFactory.waffle(with: varnish) … work with the waffle … } } } Dispatch Originally Dispatch knew nothing about autorelease pools. This meant that any work item you ran on a queue, other than the main queue, needed to set up and drain an autorelease pool. Without this it would leak. Yikes! This got worse when we added a default autorelease pool to every thread. This included the worker threads used by Dispatch. Now autoreleased objects wouldn’t leak, but rather build up in the worker thread’s autorelease pool. These would only be released when Dispatch terminated the worker thread, which in many cases never happened. Double yikes! This was fixed in macOS 10.12, where Dispatch finally got some autorelease pool smarts. There is now a pool associated with each queue and you can customise the frequency that it drains use an AutoreleaseFrequency value. Crashing Out of the Pool As a Swift programmer, your first encounter with the autorelease pool might be a crash. Consider this Swift function: 1 func simulateBadMRR() { 2 let b = (0...1023).map { _ in UInt8.random(in: 0...255) } 3 let d = NSData(bytes: b, length: b.count) 4 let du = Unmanaged.passUnretained(d) 5 print(du.takeUnretainedValue().count) 6 _ = du.autorelease() 7 } This simulates someone writing some bad MRR code. Line 4 creates a +0 reference to the NSData object and line 6 erroneously autoreleases that reference. If you call this function from Swift then, unless you’re very lucky, you won’t crash in the function itself. Remember that the function added its NSData reference to the autorelease pool, so the erroneous extra release doesn’t happen here. Rather, the function returns, and then your code returns, and eventually the thread gets back to a point where the system drains the autorelease pool. This finally performs the erroneous release and your program crashes. In the crash report you’ll see something like this: 0 libobjc.A.dylib … objc_release + 42 1 libobjc.A.dylib … AutoreleasePoolPage::releaseUntil(objc_object**) + 168 2 libobjc.A.dylib … objc_autoreleasePoolPop + 227 3 CoreFoundation … _CFAutoreleasePoolPop + 22 4 Foundation … -[NSAutoreleasePool drain] + 133 5 AppKit … -[NSApplication run] + 636 6 AppKit … NSApplicationMain + 817 7 CrashingOutOfThePool … main + 9 (AppDelegate.swift:4) 8 dyld … start + 2432 This example is from an AppKit app, and so frame 5 is the NSApplication.run() method draining the autorelease pool. Frames 4 through 1 are autorelease pool gubbins, where frame 1 actually performs the erroneous release which triggers the crash in frame 0. Debugging over release bugs like this is hard because the source of the error, the extraneous autorelease in simulateBadMRR(), is far removed from the crash. Fortunately, Apple has your back here, in the form of the zombies feature. This does two things: It replaces deallocated objects with a zombie. This traps if anyone calls it, which makes crashes like this easy to reproduce. For example, in my test app I had a button wired up to the simulateBadMRR() code and the first time I clicked that button it didn’t crash. I had to click it twice to trigger the crash. With zombies enabled, it traps on the first click. In Instruments the Zombies template enables reference count tracking, so you get a backtrace of where the object was allocated and every time its reference count was modified. For more information about the zombies feature, see my Standard Memory Debugging Tools post. Revision History 2023-03-23 Added the Crashing Out of the Pool section. 2022-09-28 First posted.
Replies
0
Boosts
0
Views
4.7k
Activity
Mar ’23
Upgrde an old app to ventura with your Xcode 4.5 source.
Hello, can upgrade an old front-end app for mac ventura 13.0? I have the complete source write in cocoa xCode e object C. When try to export app the system tell me Build fail. Have 5 error in syntax of CGColours component and conversion. The source in question is avaible for free at this link. https://mnt.conts.it/winxound/downloads/WinXound_3_4_0_OSX_Sources_XCode_4_5_0.zip Thank’s anyway.
Replies
2
Boosts
0
Views
1.2k
Activity
Mar ’23
protocol_addMethodDescription problems
Hi, I'm wondering if anyone else has seen this (and hopefully found a workaround). I'm working on a bug in PyObjC (https://github.com/ronaldoussoren/pyobjc/issues/17) related to protocols and can reproduce this in pure (Objective-)C. PyObjC creates a protocol and populates the method descriptors using the Objective-C runtime API, e.g. objc_allocateProtocol and protocol_getMethodDescription. This appears to work unreliably when adding multiple methods using protocol_getMethodDescription when the selector name and/or type encoding argument to protocol_getMethodDescription are not static strings: When the arguments are not static strings I have trouble finding the method descriptor using protocol_getMethodDescription. The code fails intermittently when adding two methods (but still fairly often), and fails reliably for me when adding 3 methods. The PyObjC issue I mentioned earlier contains a full reproducer.
Replies
1
Boosts
0
Views
716
Activity
Feb ’23
[Big Sur] /usr/lib/libobjc.A.dylib: Cannot load Swift type information
We are having a problem when we try to assign a nil value to a @objc dynamic lazy property ... The log shows this: /usr/lib/libobjc.A.dylib: Cannot load Swift type information; failed to initialize ClangImporter: error: invalid Darwin version number: macosx11.0.0 error: invalid version number in '--target = x86_64-apple-macosx11.0.0' It usually occurs when we try to assign a nil value to a @objc dynamic lazy property. (only in Big Sur beta 5 or higher) In our tearDown() logic, we manually clear references. ... // Clear strong references to objects in other MOC's result = nil // declared property that stores some coredata objects. @objc dynamic lazy var result: Result? = {[weak self] in I found this observation in the release notes: https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11-beta-release-notes Known Issues ... New in macOS Big Sur 11 beta, the system ships with a built-in dynamic linker cache of all system-provided libraries. As part of this change, copies of dynamic libraries are no longer present on the filesystem. Code that attempts to check for dynamic library presence by looking for a file at a path or enumerating a directory will fail. Instead, check for library presence by attempting to dlopen () the path, which will correctly check for the library in the cache. (62986286) ... This problem causes an application crash. Is this a mistake? Will it be available in future versions? Will it get replaced by an alternative? Thx in advance! P.s. Out of curiosity, I didn't find the /usr/lib/libobjc.A.dylib library available in Big Sur anymore, but it is present in Catalina.
Replies
2
Boosts
1
Views
4.7k
Activity
Jan ’23
Retain count and memory management
I have prepared an example to easier describe what I am want to ask: @interface ViewController () @end @implementation ViewController {   UIColor *_color; } - (void)viewDidLoad {   [super viewDidLoad];       [self getStaticVC];       __block CFTypeRef test1;   __block CFTypeRef test2;   __block CFTypeRef test3;   @autoreleasepool {     test1 = [self getVC];     test2 = [self getVC];     test3 = [self getVC];           NSLog(@"Test1: %lld", CFGetRetainCount(test1));     NSLog(@"Test2: %lld", CFGetRetainCount(test2));     NSLog(@"Test3: %lld", CFGetRetainCount(test3));   } } - (UIViewController *)getStaticVC {   static UIViewController *vc;   if (!vc) {     vc = [UIViewController new];   }   return vc; } - (CFTypeRef)getVC {   return (__bridge CFTypeRef)[self getStaticVC]; } @end For this code above, if I will run it, it will print always that retain count is 4, but if I will change implementation of the method getVC to this: - (CFTypeRef)getVC { UIViewController *temp = [self getStaticVC];   return (__bridge CFTypeRef)temp; } Code will always print retain count as 1. My guess it is related to reference storage qualifier that is assigned to returned values from this methods. For value returned from getVC there are no storage qualifier, cos it is a void *, so I guess when we assigning to UIViewController *temp it likely mean that we are getting __strong local variable that is deallocated right after getVC finish, but for my first example, it seems like getVC return an __autoreleasing reference, otherwise I have no idea why reference count is growing ?
Replies
1
Boosts
0
Views
1.4k
Activity
Jan ’23
Xcode14.1 Undefined symbol: _objc_-sgSendSuper2
as below shows, do anyone know why, and I tried this way but don't work: -fno-objc-msgsend-selector-stubs # from https://stackoverflow.com/questions/8349439/linker-cant-find-objc-msgsend-and-many-other-symbols/74108260#74108260
Replies
1
Boosts
0
Views
1.2k
Activity
Dec ’22
wkwebview.navigationdelegate is still nil after assigned delegate
I assign its navigationDelegate in my 'CustomWebView' init function, the init function is called in the viewDidLoad function and the 'CustomWebView' implements the WKNavigationDelegate functions, objection_requires(NSStringFromSelector(@selector(configRepository))) - (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration configRepository:(SKYConfigRepository *)configRepository { self = [super init]; _configRepository = configRepository; if (self) { [[JSObjection defaultInjector] injectDependencies:self]; self.converterLink = [JSObjection defaultInjector][@protocol(UniversalLinkConverterProtocol)]; WKWebViewConfiguration *wkWebViewConfig = [self getWebViewConfigWithUpdatedUserAgent:configuration]; _wkWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:wkWebViewConfig]; _wkWebView.navigationDelegate = self; ... ... then when I debug the '_wkWebView.navigationDelegate' is nil the 'self' is not nil, and it implements the WKNavigationDelegate, {   WKWebView *_wkWebView;   SKYConfigRepository *_configRepository; }
Replies
3
Boosts
0
Views
1.8k
Activity
Dec ’22