gpt4 book ai didi

objective-c - NSData/CFData 使用 @autorelease 桥接,但不使用 ARC

转载 作者:行者123 更新时间:2023-12-03 17:38:03 24 4
gpt4 key购买 nike

我有一个不使用 ARC 的库。

简化的代码如下所示:

//
// test.m
// test-cast
//

#import <Foundation/Foundation.h>

static
CFDataRef CFDataCreateFromResource(NSString *name)
{
NSURL *url = [[NSBundle mainBundle] URLForResource:name withExtension:@".bin"];

NSData *binData = [NSData dataWithContentsOfURL:url];

return (CFDataRef) binData;
}

void test(void)
{
CFDataRef data = CFDataCreateFromResource(@"Data");

if(data) CFRelease(data);
}

这是一个简化版本。测试中的代码是现有的并且要复杂得多。它手动使用各种 CFType 和 CFRelease。它最初是 C 代码。

我添加了 CFDataCreateFromResource 代码和几行在 test() 中调用它的代码,在此过程中将文件从 C 更改为 Objective-C。

这个(静态)库是从应用程序调用的,它将对 test() 的调用包装在 @autoreleasepool block 中:

int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
test();
}
NSLog(@"All done!");
return 0;
}

这里的问题是程序在 @autorelease block 末尾崩溃。看起来自动释放池正在尝试释放 CFData/NSData 对象,该对象已经被手动 CFReleased 了。

我可以删除 CFRelease,但我真的不想更改现有代码。我真正想要的是将返回的 CFDataRef 的所有权转移给调用者。

阅读有关 ARC 的内容后,我认为在转换中使用 __bridge_retained 会有所帮助。但因为这不是用 ARC 构建的,编译器给了我一个警告/错误:

error: '__bridge_retained' casts have no effect when not using ARC [-Werror,-Warc-bridge-casts-disallowed-in-nonarc] 

使用 CFDataCreateCopy 创建 NSData 的副本确实有效,但似乎很浪费。

这里处理这个问题的正确方法是什么?还有其他方法可以转换这个吗?

最佳答案

您有一个名为 CFDataCreateFromResource 的方法。这个名称意味着返回的对象正在将所有权传递给调用者。但是,此方法的实现将返回一个不属于您的自动释放对象。这违反了契约(Contract)。

一个解决方案是改变:

NSData *binData = [NSData dataWithContentsOfURL:url];

至:

NSData *binData = [[NSData alloc] initWithContentsOfURL:url];

这会更改 binData 的所有权,因此它与方法的约定相匹配。

通过这个简单的更改,您在 test 中对 CFRelease 的调用将正常工作。

关于objective-c - NSData/CFData 使用 @autorelease 桥接,但不使用 ARC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36853148/

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