一段keychain方法内存泄漏修复记录

先来看一段代码

NSMutableDictionary *attributeQuery = [query mutableCopy];
[attributeQuery setObject: (id) kCFBooleanTrue forKey:(__bridge_transfer id) kSecReturnAttributes];
CFTypeRef attrResult = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) attributeQuery, &attrResult);

这段代码在Leaks中在第四行会报内存泄漏,

image

一开始还以为是第一个参数中的__bridge问题,当把__bridge改成__bridge_retained之后内存泄漏报的更严重了。

分析:
首先这里用__bridge是没有问题的,此时attributeQuery的引用计数是1,而__bridge关键字并没有牵涉到内存管理权的转移,也就是说attributeQuery
的内存还是受ARC管理,等第四行代码运行之后attributeQuery可以正常收到release消息引用计数变为0内存被系统正常回收。那这里的问题到底出在哪呢?

这时候再仔细看后面第二个参数,传递的是一个地址,可以大胆的猜测SecItemCopyMatching内部实现中对的第二个参数指向的内存做了一次retain操作:

OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result) {
    ....
    if (result) {
        result = CFCreate(....); //retain here
    }
    ....
    return ....;
}

并且SecItemCopyMatching函数中也第二个参数前也明确有CF_RETURNS_RETAINED关键字,先来看看CF_RETURNS_RETAINED是什么:

#ifndef CF_RETURNS_RETAINED
#if __has_feature(attribute_cf_returns_retained)
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
#else
#define CF_RETURNS_RETAINED
#endif
#endif

这里有关于CF_RETURNS_RETAINED的解释。

image

意思是说有CF_RETURNS_RETAINED标记的参数或者返回值它的调用发要负责对其作release操作。
说道这里结论已经很明显了,在这段代码中由于第二个参数使用后没有release导致内存泄漏。

正确的代码应该是这样:

NSMutableDictionary *attributeQuery = [query mutableCopy];
[attributeQuery setObject: (id) kCFBooleanTrue forKey:(__bridge_transfer id) kSecReturnAttributes];
CFTypeRef attrResult = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) attributeQuery, &attrResult);

//after use attrResult ....
if (attrResult) {
    CFRelease(attrResult);
}

attrResult使用完之后需要将其release才行。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 内存管理是程序在运行时分配内存、使用内存,并在程序完成时释放内存的过程。在Objective-C中,也被看作是在众...
    蹲瓜阅读 8,443评论 1 8
  • Lancy's Blog Blog Archives About MeTwitterWeiboGitHubRSS ...
    其实也没有阅读 10,858评论 0 24
  • 一、内存管理的思考方式下文会常用到的术语解释生成对象:创建对象持有对象:引用计数+1释放对象:引用计数-1废弃对象...
    iOSUI拖拽工程师阅读 5,461评论 0 3
  • 为什么进行内存管理? 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时...
    天天想念阅读 4,394评论 1 6
  • 1,NSObject中description属性的意义,它可以重写吗?答案:每当 NSLog(@"")函数中出现 ...
    eightzg阅读 9,650评论 2 19