Swift调用takeRetainedValue/takeUnretainedValue触发EXC_BAD_ACCESS问题排查
问题分析与修复方案
问题根源
原Objective-C函数存在内存管理错误:
- 通过
CFDictionaryGetValue获取的SecIdentityRef所有权归属items数组内的字典对象。 - 执行
CFRelease(items)后,数组及内部字典会被释放,导致identityApp的引用计数归零并被销毁。 - 返回的
identityApp已变成野指针,Swift调用时触发内存访问错误。
修复代码
修改后的Objective-C函数
+ (SecIdentityRef)getSecIdentity { NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"cert1" ofType:@"p12"]; NSData *p12Data = [NSData dataWithContentsOfFile:resourcePath]; NSMutableDictionary *options = [[NSMutableDictionary alloc] init]; [options setObject:@"123456" forKey:(id)kSecImportExportPassphrase]; CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); OSStatus securityError = SecPKCS12Import((CFDataRef)p12Data, (CFDictionaryRef)options, &items); if (securityError == noErr && CFArrayGetCount(items) > 0) { CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); // 保留对象,将所有权转移给调用者 CFRetain(identityApp); CFRelease(items); return identityApp; } CFRelease(items); return NULL; }
对应的Swift调用代码
let test = Certificate.getSecIdentity() let secIdentity = test.takeRetainedValue() // 使用secIdentity完成操作后,Swift会自动管理其内存
关键说明
- 调用
CFRetain(identityApp)确保对象在items释放后仍能存活,且将所有权转移给函数调用者。 - Swift中用
takeRetainedValue()接收,符合Core Foundation的内存管理规则:谁retain谁release,Swift会自动处理后续的释放操作。
内容的提问来源于stack exchange,提问作者AntiVIRUZ
相关产品推荐
相关产品推荐

