【问题标题】:Objective-c simple memory questionObjective-c 简单记忆题
【发布时间】:2011-09-27 20:35:36
【问题描述】:

如果我的视图控制器中有变量

viewcontroller.m

@interface MemoryTestViewController : UIViewController
{
    NSMutableArray *array;
}

@end

在我的实现中

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableArray *aux = [[NSMutableArray alloc] initWithCapacity:1];
    array = aux;
    [aux release];
    // Do i have to do array release?
}

我必须在某处释放我的变量数组吗?理论上我没有分配那个变量...... 我测试了内存泄漏,即使我不释放任何东西,仪器也没有检测到任何泄漏。

【问题讨论】:

    标签: objective-c memory memory-management


    【解决方案1】:

    不,你不需要释放。您所做的就是将aux 的指针分配给您的array 变量。 array 在您释放aux 的那一刻无效。 这可能不符合预期。如果您想使用array,则必须保留它。

    【讨论】:

    • 如果我有类似 NSString *name = [[NSString alloc]...] 的内容,然后我再次执行 name = [[NSString alloc]...] 我必须释放它吗?在再次分配之前?
    • 是的。否则,您将为第一个字符串分配内存,但覆盖您对已分配内存块的引用。因此,您以后将无法发布它。您应该在 Google 上搜索“ios 内存管理”并阅读 Apple 的指南。有了自动引用计数的 iOS5,事情会变得更简单。
    • 我可以在第一次分配之后做类似 [name initWithString:...] 的事情吗?
    • 是的,但是你会泄漏内存,因为第一个字符串不会被释放。您必须学习诸如“仅发布您拥有的东西”之类的基础知识。阅读内存管理指南:developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/…
    • @Marc:不!你不能(好吧,should not)重新初始化一个实例 /cc @Krumelur
    【解决方案2】:

    您已经使用[aux release]; 释放了数组——实际上,您遇到了与泄漏相反的问题:过度释放。

    Objective-C 中的赋值只是指针的赋值;没有复制或自动memory management。当您说array = aux; 时,array 现在指向与aux 完全相同的对象。如果您随后通过释放 aux 来摆脱它(因此让它被释放),array 不再指向任何东西。*

    你有几个选项可以解决这个问题:

    1. (最简单)将新建的数组直接赋值给array

      array = [[NSMutableArray alloc] initWithCapacity:1];

      这使您拥有新阵列的所有权,名称为array。在完成之前不要释放它(可能在dealloc;当然不是在这个方法中)。

    2. (最佳)为array 创建一个declared property 并让该机制为您处理内存管理:

    
    @interface MemoryTestViewController : UIViewController
    {
        NSMutableArray *array;  
    }  
    
    @property (copy, nonatomic, setter=setArrayByMutableCopy) NSMutableArray * array;
    @end
    
    @implementation MemoryTestViewController
    @synthesize array;
    
    // Properties can't automatically make mutable copies, so you need to create
    // your own setter method.
    - (void) setArrayByMutableCopy: (NSMutableArray *)newArray {
        NSMutableArray * tmp = [newArray mutableCopy];
        [array release];
        array = tmp;
    }
    ...
    
    

    *或者,更确切地说,它指向一个曾经存在有效对象的地方,这是让你的程序崩溃的好方法。

    【讨论】:

      【解决方案3】:

      没有。将对象分配给变量不会保留它。但是,如果您打算暂时使用该变量,则应保留它并在使用完后释放它。

      alloc 将保留计数器提高到 1 并且 [aux release] 将其设置为 0

      【讨论】:

      • alloc 给对象保留计数 1,not init...
      【解决方案4】:

      你应该添加一个属性:

      @property (nonatomic, 保留) NSMutableArray *array;

      稍后在您的 viewDidLoad 中:

      // 错误,泄漏:self.array = [[NSMutableArray alloc] initWithCapacity:1];

      array = [[NSMutableArray alloc] initWithCapacity:1];

      是的,稍后发布它,可能在 dealloc..

      【讨论】:

      • 此声明 self.array = [[NSMutableArray alloc] initWithCapacity:1]; 泄漏。应该是self.array = [[[NSMutableArray alloc] initWithCapacity:1] autorelease];。 autorelease平衡alloc-init,property setter保留对象,由dealloc中对应的release平衡。
      • 我写了“...稍后发布它”。
      • 那样做,你没有参考,你以后可以发布它(严格来说,可以在这之后[self.array release],但是是一种非常糟糕的代码气味。通常每个保留应该有一个指针——IOW,每个引用计数都有一个引用。/cc @albertamg
      猜你喜欢
      • 2013-02-08
      • 1970-01-01
      • 1970-01-01
      • 2014-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      相关资源
      最近更新 更多