ARC导致CoreFoundation对象崩溃

时间:2016-10-19 11:15:04

标签: ios objective-c macos cocoa automatic-ref-counting

我有一部分代码有时会在客户端的OSX系统上崩溃,但我无法重现崩溃。我只有很少的假设,但我不想盲目修复。我只想通过修复确信:

+ (NSArray *)loginItems:(NSError *__autoreleasing *)error {

    LSSharedFileListRef list = [self loginItemsFileListRef];
    NSMutableArray *result = [NSMutableArray array];
    NSArray *items = [self loginItemsForFileListRef:list];
    CFRelease(list);
    for (id item in items) {
        LSSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item;
        [result addObject:[self loginItemFromItemRef:itemRef]];
    }
    return result;
}

+ (NSDictionary *)loginItemFromItemRef:(LSSharedFileListItemRef)itemRef {
    NSMutableDictionary *itemDict = [NSMutableDictionary dictionary];
    // Name
    CFStringRef nameRef = LSSharedFileListItemCopyDisplayName(itemRef);
    if (nameRef) {
        NSString *name = (__bridge NSString *)nameRef;
        itemDict[RESLoginItemsNameKey] = name.stringByDeletingPathExtension;
        CFRelease(nameRef);
    }
    // Path
    CFURLRef URLRef = NULL;
    if (LSSharedFileListItemResolve(itemRef, 0, &URLRef, NULL) == noErr) {
        if (URLRef) {
            NSURL *URL = (__bridge NSURL *)URLRef;
            NSString *path = URL.path;
            if (path) {
                itemDict[RESLoginItemsPathKey] = path;
            }
            CFRelease(URLRef);
        }
    }
    // Hidden
    CFBooleanRef hiddenRef = LSSharedFileListItemCopyProperty(itemRef,
                                                              kLSSharedFileListLoginItemHidden);
    if (hiddenRef) {
        if (hiddenRef == kCFBooleanTrue) {
            itemDict[RESLoginItemsHiddenKey] = @YES;
        }
        CFRelease(hiddenRef);
    }

    return itemDict;
}

loginItems 中的崩溃:即 SharedFileListItemDeallocate 导致崩溃。当NSArray的物品自动释放时。我想:

SSharedFileListItemRef itemRef = (__bridge LSSharedFileListItemRef)item;

打破ARC行为,当循环结束时,它导致释放数组的具体项目。第二个版本将在函数返回时被调用,这将导致崩溃。

有人可以证明或反驳我的想法吗?感谢。

1 个答案:

答案 0 :(得分:0)

我认为问题在于您在使用

返回的项目之前发布了list
[self loginItemsForFileListRef:list]

如果返回的项取决于list是否有效,因为list的发布也可能触发items的释放,那么当您尝试迭代返回时可能会崩溃项目。尝试在迭代list的for循环之后移动items的版本。如果你试图过度使用内存使用,有时你会被咬伤。