指针设置为nil时的Objective-C引用计数(不带ARC)

时间:2015-02-24 00:59:03

标签: objective-c xcode reference-counting

我试图了解引用计数是如何工作的,所以我禁用了ARC并编写了一个简单的类:( Foo.h未粘贴,因为它未被修改)

Foo.m

@implementation Foo

- (instancetype)init
{
    NSLog(@"Init object");
    return [super init];
}

- (void)dealloc
{
    NSLog(@"Dealloc object");
    [super dealloc];
}

@end

的main.m

#import <Foundation/Foundation.h>
#import "Foo.h"

int main(int argc, const char * argv[]) {

    Foo *obj = [[Foo alloc] init];

    obj = nil;
    return 0;
}

现在我希望看到dealloc object日志,因为对Foo对象的唯一引用已经消失,但我收到的唯一消息是init object

为什么我不明白?当我分配obj = nil

时,是否释放了该对象

2 个答案:

答案 0 :(得分:5)

没有。如果您不使用ARC,则在致电[obj release];时会释放该对象。 (ARC为您插入这些调用。)将obj设置为nil在内存管理方面没有任何作用(尽管它确实创建了一个您无法再访问的对象!)。

基本上,在没有ARC的Cocoa中:

  • 如果您想取得对象的所有权,请致电[obj retain]。 (alloc为你做这件事。)
  • 当您想放弃对象的所有权时,请致电[obj release]。当对象的保留计数达到0时,release依次调用dealloc
  • 当您想要放弃当前范围之外的对象的所有权时,请致电[obj autorelease]。最常见的情况是,当您从方法返回一个对象时(并且不想保留对它的所有权),会发生这种情况。

答案 1 :(得分:1)

另外一些观察要扩展mipadi的优秀答案:

  1. 在非ARC代码中,将变量设置为nil释放该对象。您必须明确release / autorelease它。

    更准确地说,如果所有权已转移给您(即您从名称以allocnewcopy开头的方法获取对象,或者mutableCopy),然后您负责明确调用release / autorelease

    底线,只是将变量设置为nil是不够的。

  2. 我因为担心这个问题蒙上阴影而犹豫不决,但在处理属性时,它有点不同。使用属性,调用retain属性的setter将自动retain对象为您。如果您稍后将属性设置为nil,则设置者自动release为您提供。

    想象一下这样的课程:

    @interface Bar : NSObject
    @property (nonatomic, retain) Foo *foo;
    @end
    

    如果要设置foo属性,可以执行以下操作

    Foo *f = [[Foo alloc] init];  // create Foo object with +1 retain count
    self.foo = f;                 // the `retain` property will increase retain count to +2
    [f release];                  // resolve the local strong reference, reducing retain count back to +1
    

    或者更简单:

    self.foo = [[[Foo alloc] init] autorelease];
    

    这样做会创建一个具有+1保留计数的Foo对象。通过设置foo属性,您将创建另一个strong引用,从而最终得到+2保留计数。然后,当您release / autorelease时,保留计数会回落到+1。

    稍后,当您完成foo并想要发布它时,您只需再次调用setter,这次使用nil值:

    self.foo = nil;              // resolve the `retain` done by the property, reducing the retain count to +0
    

    这减轻了对foo属性维护的强大参考。您自己致电release(至少在酒店上)。显然,当您使用nil值调用setter时,不仅会释放上一个对象,但如果这是最后一个强引用,那么该对象也将被释放。

  3. 简而言之,原始allocrelease / autorelease偏移,而不是将变量设置为nil。但是,通过将该属性设置为retain来解析nil属性的设置


    最后几点意见。

    • 我建议如果编写非ARC代码,请仔细查看高级内存管理编程指南,,特别是Memory Management Policy章。

    • Xcode的静态分析器( shift + 命令 + B ,或&#34;分析&#34;在Xcode&#34;产品&#34;菜单上)非常适合识别困扰非ARC代码的内存问题。始终确保静态分析仪绝对没有警告。

    • 使用Instruments时,分配工具有一个名为&#34;记录参考计数&#34; (见https://stackoverflow.com/a/14105056/1271826)。如果您发现某个对象未被释放,则此工具可用于诊断对象的整个生命周期,并且所有对象都可以保留计数。