2012-12-13 59 views
1

我有一个使用ARC库的非ARC项目。如果我应该释放库方法返回的对象,我很困惑。这里有一些例子:从非ARC代码调用ARC方法

- (void)test{ 
    LibObject* obj1 = [[LibObject alloc] init]; 
    LibObject* obj2 = [obj1 otherObj]; 

    [obj1 release]; //should I release it? 
    [obj2 release]; //should I release it? 
} 

就我所知,如果对象在autorelease池中,我应该放弃它。否则,我应该释放它。

然而,the ARC document

当从这样的函数或方法返回,ARC保留在return语句的评价点的值,然后离开所有本地范围,然后平衡了保留同时确保价值贯穿呼叫边界。在最坏的情况下,这可能涉及自动释放,但呼叫者不能认为该值实际上在自动释放池中。

该文件是否意味着我应该始终释放该对象,因为我不能假定该对象是autoreleased?

回答

3

Memory Management Policy在“高级内存管理编程指南”:

你拥有的任何对象创建
您使用的方法 名称以“黄金”,“新创建一个对象“,”copy“或”mutableCopy“(对于 示例,alloc,newObject或mutableCopy)。

你一定不会放弃对象的所有权不属于您

这些规则与ARC编译的方法是一致的。 在ARC documentation,在第一类方法的行为中的“3.2.2保留返回值”被描述:

当从这样的功能或方法返回,ARC在点保留值 评估退货声明,...

这意味着调用者必须释放该对象。在第二类

的方法在“3.2.3非保留返回值”中描述:

当从这样的功能或方法返回,ARC在返回的评价点保留值 声明,然后离开所有 本地示波器,然后余额保留...

这意味着调用方不得释放该对象。

所以在你的例子:

LibObject* obj1 = [[LibObject alloc] init]; 
LibObject* obj2 = [obj1 otherObj]; 
[obj1 release]; //should I release it? --> YES 
[obj2 release]; //should I release it? --> NO 

您拥有obj1,因为它与alloc创建的,所以你必须释放obj1。您不拥有obj2,因此您不得释放它。

注意:如果您在代码上运行Xcode静态分析器,它会精确显示违反这些规则的位置。

0

我的理解是,如果你使用编译器标志-fno-objc-arc这个文件,你需要自己照顾保留/释放。所以你应该打电话[obj1 release]。如果你不应该自己调用它,编译器会相应地提醒你。

2

当您从ARC启用的类中获取对象到您的非ARC启用类时,您有责任管理内存。

ARC只是在编译时间期间简单地将保留,释放到ARC启用代码中。它不会管理处于非ARC模式的其他类或对象上的内存。

您应该在需要后释放这些对象。

0

我的理解是,在您的非ARC代码中,您只需像往常一样使用支持ARC的库来执行所有retain/release(就像与其他非ARC代码交互一样)。

我创建了一个简单的应用程序来证明这种行为。

测试代码 - 不 ARC

- (void)testARC 
{ 
    ARCLib *al = [[ARCLib alloc] init]; 
    NSLog(@"%p retainCount = %u", al, [al retainCount]); 
    [al release]; 

    ARCLib *al2 = [ARCLib arcLib]; 
    NSLog(@"%p retainCount = %u", al2, [al2 retainCount]); 
} 

ARCLib编译- 编译 ARC

@implementation ARCLib 

+ (id)arcLib 
{ 
    return [[self alloc] init]; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) 
    { 
     NSLog(@"%p init",self); 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    NSLog(@"%p dealloc",self); 
} 

@end 

结果

2012-12-13 20:15:21.879 ARCTest[15206:907] 0x1e821500 init 
2012-12-13 20:15:21.883 ARCTest[15206:907] 0x1e821500 retainCount = 1 
2012-12-13 20:15:21.884 ARCTest[15206:907] 0x1e821500 dealloc 
2012-12-13 20:15:21.885 ARCTest[15206:907] 0x1dd26060 init 
2012-12-13 20:15:21.886 ARCTest[15206:907] 0x1dd26060 retainCount = 1 
2012-12-13 20:15:21.893 ARCTest[15206:907] 0x1dd26060 dealloc 

回答你的问题

你应该释放你的obj1,但不需要释放obj2。

+0

这实际上并不能证明任何事情,因为'retainCount'既不会反映自动释放状态,也不会反映任何在线程(或任何内部实现细节)上的活动。巧合,你的结论是正确的。 – bbum

+0

@bbum你误解了我的代码。这里的retainCount没有显示任何内容。演示代码证明了底层autorelease池为我们做了魔术。 – howanghk

+0

那么为什么有retainCount呢?返回的值在此上下文中无用。 – bbum