gpt4 book ai didi

ios - 使用 ARC 的安全框架内存泄漏

转载 作者:行者123 更新时间:2023-11-28 18:06:02 26 4
gpt4 key购买 nike

我在为 ASIHTTPRequest 打开 p12 证书时遇到内存泄漏。这是我获取证书的代码:

- (SecIdentityRef)getClientCertificate {
SecIdentityRef identityApp = nil;
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"myCert" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
CFStringRef password = CFSTR("myPassword");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
CFRelease(options);
CFRelease(password);
if (securityError == errSecSuccess) {
NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
} else {
NSLog(@"Error opening Certificate.");
}
return identityApp;
}

如您所见,它会产生内存泄漏: enter image description here

或者,这个其他函数(基本相同)会产生其他类型的内存泄漏:

- (SecIdentityRef)getClientCertificate2 {
SecIdentityRef identityApp = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *thePath = [documentsDirectory stringByAppendingPathComponent:@"myothercert.p12"];

NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
NSLog(@"PKCS12Data length is %i", [PKCS12Data length]);
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;

CFStringRef password = CFSTR("randomgenerated");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
CFRelease(options);
//CFRelease(password);
if (securityError == errSecSuccess) {
NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
} else {
NSLog(@"Error opening Certificate.");
}
return identityApp;
}

产生这些内存泄漏: enter image description here

是什么导致了这些内存泄漏?该代码可以很好地打开 p12 文件,但我需要修复内存泄漏。任何帮助表示赞赏。

谢谢!

EDIT

根据建议的更改,我仍然收到内存泄漏:

- (SecIdentityRef)copyClientCertificate2 {
SecIdentityRef identityApp = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *thePath = [documentsDirectory stringByAppendingPathComponent:@"cert.p12"];

NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
NSLog(@"PKCS12Data length is %i", [PKCS12Data length]);


CFStringRef password = CFSTR("randomgenerated");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = NULL;
OSStatus securityError = SecPKCS12Import((__bridge CFDataRef)PKCS12Data, options, &items);
CFRelease(options);
//CFRelease(password);
if (securityError == errSecSuccess) {
NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
} else {
NSLog(@"Error opening Certificate.");
}
CFRetain(identityApp);
return identityApp;

最佳答案

您正在泄漏项目。您创建它但从不释放它。你不应该首先创建它。 SecPKCS12Import 通过引用返回 items。您不会将其传递给现有的;它超过了一个。这应该是:

CFArrayRef items = NULL;

您还需要在 identityApp 上调用 CFRetain() 来保留它(因为它目前仅由数组保留。因此,您的方法需要称为 copyClientCertificate2 并且您需要在完成后CFRelease() 它的结果。

旁注:永远不要在方法前加上“get”,除非它通过引用返回结果。这就是“获取”在 ObjC 中的意思。例如:

- (BOOL)getName:(NSString **)name;

这里还有一段非常危险的代码:

NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; // (1)
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data; // (2)
...
OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items); // (3)

ARC 可以在第 (2) 行之后立即免费发布 PKCS12Data。如果您在 Release模式下构建它,我希望它会崩溃。此处正确的解决方案是摆脱 inPKCS12Data,并执行第 (3) 行的 __bridge 转换。


编辑:

如果您从事此类工作,了解如何管理 Core Foundation 对象非常重要。首先,研究下面链接的创建规则。然后,调用方法 copy... 的目的是指示调用者负责对返回的对象调用 CFRelease。它看起来像这样:

SecIdentityRef identity = [self copyClientCertificate2];
... Do what you need to do with identity ....
CFRelease(identity);

由于您从不在 copyClientCertificate2 中使用 self,因此将它变成一个函数对您来说可能更有意义,这样它看起来就像其他 Core Foundation 函数:

SecIdentityRef identity = MYSecIdentityCopyClientCertificate();
... Do what you need to do with identity ....
CFRelease(identity);

注意函数名称中的单词Copy

关于ios - 使用 ARC 的安全框架内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19430710/

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