无法解决CoreFoundation对象中的内存泄漏

时间:2014-05-20 13:07:06

标签: ios iphone memory-leaks abaddressbook

我使用以下代码删除我在地址簿中插入的所有联系人,具体取决于他们已添加到的group

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);

NSArray* contactsArray = (__bridge NSArray *)(ABGroupCopyArrayOfAllMembers([self ABGetAddressGroup:addressBook]));

if (contactsArray.count) {

    for (NSUInteger index = 0 ; index < contactsArray.count; index++) {

        ABRecordRef person = (__bridge ABRecordRef)(contactsArray[index]);

        ABAddressBookRemoveRecord(addressBook, person, NULL);
    }

    CFRelease((__bridge CFTypeRef)contactsArray);

    NSArray *groups = (__bridge NSArray *) ABAddressBookCopyArrayOfAllGroups(addressBook);

    for (id _group in groups) {

        NSString *currentGroupName = (__bridge NSString*) ABRecordCopyValue((__bridge ABRecordRef)(_group), kABGroupNameProperty);

        if ([[self getDatabase] isEqualToString:currentGroupName]) {

            ABAddressBookRemoveRecord(addressBook, (__bridge ABRecordRef)(_group), NULL);
        }

        CFRelease((__bridge CFTypeRef)(currentGroupName));
    }

    CFRelease((__bridge CFTypeRef)(groups));
}

if (ABAddressBookHasUnsavedChanges(addressBook)) {//potential leak of an object stored in contactsArray

    //Save recent changes
    ABAddressBookSave(addressBook, NULL);

} else {

    NSLog(@"Nothing to do here, let's eat cake");
}

CFRelease(addressBook);

分析器会在ABAddressBookHasUnsavedChanges ... potential leak of an object stored in contactsArray中显示警告(如果它被称为“#1}}”。我需要做些什么来摆脱这个?

如果使用CFRelease如下:

CFRelease((__bridge CFTypeRef)(contactsArray));

分析器说:Reference-counted object is used after it is released,即使它在非返回方法结束时发布,并且应用程序崩溃。

我在这里做错了什么?如何摆脱这种内存泄漏?

1 个答案:

答案 0 :(得分:3)

你的问题就在这一行:

CFRelease((__bridge CFTypeRef)contactsArray);

因为当执行if语句的true-branch时,此行仅运行 ,因此在其他所有方案中都不会释放contactsArray。那里泄漏。

幸运的是,有两种方法可以解决这个简单的问题。

选项#1

将所有权传递给ARC

NSArray* contactsArray = (__bridge_transfer NSArray *)(ABGroupCopyArrayOfAllMembers([self ABGetAddressGroup:addressBook]));

if (contactsArray.count) {
     // (...)

     // CFRelease((__bridge CFTypeRef)contactsArray);

     // (...)
}

选项#2

确保在任何情况下都释放该对象:

NSArray* contactsArray = (__bridge NSArray *)(ABGroupCopyArrayOfAllMembers([self ABGetAddressGroup:addressBook]));

if (contactsArray.count) {
     // (...)

     // CFRelease((__bridge CFTypeRef)contactsArray);

     // (...)
}

if (contactsArray) CFRelease((__bridge CFTypeRef)contactsArray);

这样的事情对你有帮助,我想。