使用 CFRelease 时发生内存泄漏
Memoryleak when using CFRelease
我有仪器显示内存泄漏的方法:
-(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);在 return hasGroup 之前,它崩溃了。
我不明白这里发生了什么。
静态分析器(shift+command+B or "Analyze"在 Xcode 的 "Product" 菜单上)非常擅长为您识别这些问题:
最重要的是,Create Rule 规定您必须 CFRelease
从 Core Foundation 函数返回的任何名称中带有 Copy
或 Create
的对象(除了那些您可以使用 CFBridgingRelease
或 __bridge_transfer
转让所有权,因为这允许 ARC 为您清理这些)。
不用说,你不应该 CFRelease
其他任何东西(例如 group
,它是由名称中没有 Copy
或 Create
的函数返回的,也不是 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)
的尝试由于其他原因而崩溃(例如,ab
是 NULL
因为 ABAddressBookCreateWithOptions
失败了,也许您忽略了添加 NSContactsUsageDescription
到你的 plist;ab
在随后引用 ab
之前发布;你发布了你不应该拥有的东西;你从一些 Core Foundation 功能收到 NULL
并试图 CFRelease
那个;等等)。但是上面的内容应该可以正常工作,因为它解决了上述问题。
显然,如果仅使用 iOS 9 及更高版本,您可以使用 Contacts.framework 并完全避免所有这些桥接烦恼。
我有仪器显示内存泄漏的方法:
-(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);在 return hasGroup 之前,它崩溃了。 我不明白这里发生了什么。
静态分析器(shift+command+B or "Analyze"在 Xcode 的 "Product" 菜单上)非常擅长为您识别这些问题:
最重要的是,Create Rule 规定您必须 CFRelease
从 Core Foundation 函数返回的任何名称中带有 Copy
或 Create
的对象(除了那些您可以使用 CFBridgingRelease
或 __bridge_transfer
转让所有权,因为这允许 ARC 为您清理这些)。
不用说,你不应该 CFRelease
其他任何东西(例如 group
,它是由名称中没有 Copy
或 Create
的函数返回的,也不是 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)
的尝试由于其他原因而崩溃(例如,ab
是 NULL
因为 ABAddressBookCreateWithOptions
失败了,也许您忽略了添加 NSContactsUsageDescription
到你的 plist;ab
在随后引用 ab
之前发布;你发布了你不应该拥有的东西;你从一些 Core Foundation 功能收到 NULL
并试图 CFRelease
那个;等等)。但是上面的内容应该可以正常工作,因为它解决了上述问题。
显然,如果仅使用 iOS 9 及更高版本,您可以使用 Contacts.framework 并完全避免所有这些桥接烦恼。