You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 13:11:37