1

我有一个使用 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?
}

据我所知,如果对象在自动释放池中,我应该不理会它。否则,我应该释放它。

然而,ARC文件

当从这样的函数或方法返回时,ARC 在返回语句的求值点保留值,然后离开所有局部范围,然后平衡保留,同时确保值跨越调用边界。在最坏的情况下,这可能涉及自动释放,但调用者不能假定该值实际上在自动释放池中。

该文件是否暗示我应该始终释放该对象,因为我不能假设该对象是自动释放的?

4

4 回答 4

4

请参阅《高级内存管理编程指南》中的内存管理策略:

您拥有您创建的任何对象 您
使用名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法创建对象(例如,alloc、newObject 或 mutableCopy)。

您不得放弃您不拥有的对象的所有权

这些规则与使用 ARC 编译的方法一致。在ARC 文档中,第一类方法的行为在“3.2.2. Retained return values”中描述:

从这样的函数或方法返回时,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 静态分析器,它会准确显示违反这些规则的位置。

于 2012-12-13T12:30:10.403 回答
2

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

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

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

于 2012-12-13T11:49:18.050 回答
0

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

于 2012-12-13T11:47:20.277 回答
0

据我了解,在您的非 ARC 代码中,您只需像往常一样使用启用 ARC 的库执行所有保留/释放(就像与其他非 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。

于 2012-12-13T12:20:38.990 回答