ndg*_*ndg 5 memory cocoa memory-leaks objective-c
我正在转换一个Objective-C函数,它将CFStringRef转换为类似的NSString(其中FSEventStreamCopyDescription返回一个CFStringRef):
return (NSString *)FSEventStreamCopyDescription(eventStream);
Run Code Online (Sandbox Code Playgroud)
但是,在分析我的应用程序时,我被告知由于缺少CFRelease调用,这将导致"潜在泄漏".我正在尝试重写此函数以避免任何泄漏.处理这个问题的正确方法是什么?我提供了两种可能性(两者都可能不正确):
选项A:
CFStringRef ref = FSEventStreamCopyDescription(eventStream);
NSString *desc = [(NSString *)ref copy];
CFRelease(ref);
return [desc autorelease];
Run Code Online (Sandbox Code Playgroud)
选项B:
CFStringRef ref = FSEventStreamCopyDescription(eventStream);
NSString *desc = [[NSString alloc] initWithString:(NSString *)ref];
CFRelease(ref);
return [desc autorelease];
Run Code Online (Sandbox Code Playgroud)
Casting对该对象没有任何作用.演员只会告诉编译器"这真的是一个_____".
它对内存管理规则也没有任何作用.您仍然拥有一个从遵循CF规则并在其名称中包含Copy的函数中获取的对象.因此,你拥有那个对象; 因此,你有责任释放它.
重要的不是班级的名称; 免费桥接意味着CFString 是 NSString.重要的是规则从下面得到对象的函数或方法(CF规则或基础规则),以及是否遵守它们.
选项A和B都解决了问题,但复杂性过高.
选项A中的复制和发布无效.你已经复制了它; 制作另一份副本不会改变这种情况.它只会浪费你的时间和用户的时间.
选项B 的initWithString:(或stringWithString:)也没有实现.您已经有一个CFString,而CFString是一个NSString,因此您不需要创建NSString.最终,这相当于选项A.
@ kubi的回答是迄今为止最好的,但有一个改进:
return [NSMakeCollectable(FSEventStreamCopyDescription(eventStream)) autorelease];
Run Code Online (Sandbox Code Playgroud)
通过此更改,代码将在垃圾收集下正常工作,autorelease无需执行任何操作.同时,根据保留/释放规则,NSMakeCollectable什么都不做.无论哪种方式,您的所有权将在适当的时间发布/收集.