2017-06-20 62 views
1

当我有这导致如由仪器内存泄漏的方法,包括:Memoryleak使用CFRelease

enter image description here

-(BOOL)checkIfGroupExistWithName:(NSString*)groupName 
{ 
    BOOL hasGroup = NO; 
    //checks to see if the group is created ad creats group for Handheld contacts 

    CFErrorRef error = NULL; 
    ABAddressBookRef ab = ABAddressBookCreateWithOptions(NULL, &error); 

    CFIndex groupCount = ABAddressBookGetGroupCount(ab); 
    CFArrayRef allGroups = ABAddressBookCopyArrayOfAllGroups(ab); 

    for (int i=0; i<groupCount; i++) { 

     ABRecordRef group = CFArrayGetValueAtIndex(allGroups, i); 

     CFStringRef CFcurrentGroupName = ABRecordCopyCompositeName(group); 
     NSString *currentGroupName = (__bridge_transfer NSString *)CFcurrentGroupName; 

     if ([currentGroupName isEqualToString:groupName]) { 
      //!!! important - save groupID for later use 
      groupId = ABRecordGetRecordID(group); 
      hasGroup = YES; 
      i = (int) groupCount; 
     } 
     CFRelease(CFcurrentGroupName); 
     CFRelease(group); 
    } 


    return hasGroup; 
} 

如果使用CFRelease(AB);在返回hasGroup之前,它崩溃了。 我无法理解这里发生了什么。

回答

3

静态分析(转变 + 命令 + 或 “分析” 的Xcode的 “产品” 菜单上)是非常善于识别这些问题为您提供:

enter image description here

底行,Create Rule指示您必须CFRelease从Core Foundation函数返回的任何对象的名称中包含CopyCreate(除了那些将您的所有权转让给或者CFBridgingRelease__bridge_transfer,因为这可以让ARC为您清理这些)。

不用说,你不应该CFRelease别的(如group,这是由一个功能,无需在名称CopyCreate回来,也不CFcurrentGroupName,你已经转移所有权__bridge_transfer)。

无论如何,你最终的东西,如:

- (BOOL)checkIfGroupExistWithName:(NSString*)groupName { 
    BOOL hasGroup = NO; 
    //checks to see if the group is created ad creats group for Handheld contacts 

    CFErrorRef error = NULL; 
    ABAddressBookRef ab = ABAddressBookCreateWithOptions(NULL, &error); 
    if (!ab) { 
     NSLog(@"%@", CFBridgingRelease(error)); 
     return false; 
    } 

    CFIndex groupCount = ABAddressBookGetGroupCount(ab); 
    CFArrayRef allGroups = ABAddressBookCopyArrayOfAllGroups(ab); 

    for (int i = 0; i < groupCount; i++) { 

     ABRecordRef group = CFArrayGetValueAtIndex(allGroups, i); 

     NSString *currentGroupName = CFBridgingRelease(ABRecordCopyCompositeName(group)); 

     if ([currentGroupName isEqualToString:groupName]) { 
      //!!! important - save groupID for later use 
      groupId = ABRecordGetRecordID(group); 
      hasGroup = true; 
      break; 
     } 
    } 

    if (allGroups) CFRelease(allGroups); 
    CFRelease(ab); 

    return hasGroup; 
} 

我怀疑你的企图CFRelease(ab)被撞毁其他原因(如abNULL因为ABAddressBookCreateWithOptions失败,也许你忘了添加NSContactsUsageDescription到您的plist; ab在随后引用ab之前被释放;您正在释放您不应该拥有的东西;您从某个Core Foundation功能收到NULL,并尝试登录CFRelease;等等)。但是,上述应该可以很好地解决上述问题。显然,如果仅使用iOS 9和更高版本,则可以使用Contacts.framework并完全避免所有这些桥接问题。