gpt4 book ai didi

iphone - SecItemCopyMatching 在 ARC 下的 osx 上仍然存在泄漏

转载 作者:行者123 更新时间:2023-12-03 16:49:35 28 4
gpt4 key购买 nike

我在 SecItemCopyMatching 上发现内存泄漏。经过对 SF 的调查,我找到了解决方案:

__block NSString *certificateName = nil;
SecKeychainRef keychain;
SecKeychainCopyDefault(&keychain);
NSMutableDictionary *attributeQuery = [NSMutableDictionary dictionary];
[attributeQuery setObject: (id) kSecClassIdentity forKey:(__bridge_transfer id) kSecClass];
[attributeQuery setObject: (id) kCFBooleanTrue forKey:(__bridge_transfer id) kSecReturnRef];
[attributeQuery setObject: (id) kSecMatchLimitAll forKey:(__bridge_transfer id) kSecMatchLimit];
CFTypeRef attrResult = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) attributeQuery,(CFTypeRef *) &attrResult);<------- here is a leak according Instruments


if (status != errSecItemNotFound) {
NSArray *attributeResult = (__bridge_transfer NSArray *)attrResult;
[attributeResult enumerateObjectsUsingBlock:^(id identityFromArray, NSUInteger idx, BOOL *stop) {
OSStatus status;
SecCertificateRef cert = NULL;
status = SecIdentityCopyCertificate((__bridge SecIdentityRef)identityFromArray, &cert);
if (!status)
{

或其他解决方案:

NSMutableDictionary *attributeQuery = [NSMutableDictionary dictionary];
[attributeQuery setObject: (id) kSecClassIdentity forKey:(__bridge_transfer id) kSecClass];
[attributeQuery setObject: (id) kCFBooleanTrue forKey:(__bridge_transfer id) kSecReturnRef];
[attributeQuery setObject: (id) kSecMatchLimitAll forKey:(__bridge_transfer id) kSecMatchLimit];
CFTypeRef attrResult = NULL;
CFDictionaryRef cfquery = (__bridge_retained CFDictionaryRef)attributeQuery;
OSStatus status = SecItemCopyMatching(cfquery,(CFTypeRef *) &attrResult);<------- here is a leak according Instruments


if (status != errSecItemNotFound) {
NSArray *attributeResult = (__bridge_transfer NSArray *)attrResult;
[attributeResult enumerateObjectsUsingBlock:^(id identityFromArray, NSUInteger idx, BOOL *stop) {
OSStatus status;
SecCertificateRef cert = NULL;
status = SecIdentityCopyCertificate((__bridge SecIdentityRef)identityFromArray, &cert);
if (!status)
{
char *nameBuf = NULL;
CFStringRef nameRef = NULL;
OSStatus statusNew = SecCertificateInferLabel(cert, &nameRef);
.....
CFRelease(cfquery)

但他们仍然对我来说泄漏。

还有什么想法

最佳答案

  • 您从名称中带有 Copy 的 CF 样式函数接收钥匙串(keychain)对象。因此它有一个 +1 引用计数,并且您有责任在使用完它后显式释放它。您的示例代码从未发布它,因此它正在泄漏。您发布的代码中从未使用过钥匙串(keychain)对象,因此可以完全消除它。
  • 在第一个解决方案中,您通过简单的 __bridge 转换传递 attributeQuery (局部变量),这不是一个好主意; ARC 可能会过早地从你的脚下释放它。您应该使用 __bridge_retained(或 CFBridgingRetain)将其转换为保留计数 +1 的 CF 国家/地区(并在稍后明确释放它)。
  • 在第二个解决方案中,您使用了 __bridge_retained,但没有发布结果,这解释了泄漏的原因。
  • 如果调用成功,SecItemCopyMatching 的返回值为零。您不应仅与 errSecItemNotFound 进行比较;查询失败可能有多种其他原因。

更新的代码:

NSMutableDictionary *attributeQuery = [NSMutableDictionary dictionary];
[attributeQuery setObject:(id)kSecClassIdentity forKey:(__bridge id)kSecClass];
[attributeQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnRef];
[attributeQuery setObject:(id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
CFTypeRef cfresult = NULL;
CFDictionaryRef cfquery = (CFDictionaryRef)CFBridgingRetain(attributeQuery);
OSStatus status = SecItemCopyMatching(cfquery, &cfresult);
CFRelease(cfquery);

if (status == errSecSuccess) {
NSArray *attributeResult = CFBridgingRelease(cfresult);
[attributeResult enumerateObjectsUsingBlock:^(id value, NSUInteger idx, BOOL *stop) {
OSStatus status;
SecCertificateRef cert = NULL;
SecIdentityRef identity = CFBridgingRetain(value);
status = SecIdentityCopyCertificate(identity, &cert);
CFRelease(identity);
if (!status)
{
...
CFRelease(cert);
}];
}

我发现 Core Foundation/Cocoa 桥接转换有点难以阅读,因此我个人认为跳过 Cocoa 级别并直接在 CF 级别上创建查询字典会更干净,如下所示:

CFMutableDictionaryRef cfquery = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(cfquery, kSecClass, kSecClassIdentity);
CFDictionarySetValue(cfquery, kSecReturnRef, kCFBoolenTrue);
CFDictionarySetValue(cfquery, kSecMatchLimit, kSecMatchLimitAll);

CFArrayRef cfidentities = NULL;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)cfquery, (CFTypeRef *)&cfidentities);
CFRelease(cfquery);

if (status == errSecSuccess) {
NSArray *identities = CFBridgingRelease(cfidentities);
for (id value in identities) {
SecCertificateRef cfcertificate;
SecIdentityRef cfidentity = (SecIdentityRef)CFBridgingRetain(value);
status = SecIdentityCopyCertificate(cfidentity, &cfcertificate);
if (status == errSecSuccess) {
// ...
CFRelease(cfcertificate);
}
}
}

关于iphone - SecItemCopyMatching 在 ARC 下的 osx 上仍然存在泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16780202/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com