在方法中创建自动释放的对象并将其返回到实例化变量会导致崩溃

时间:2010-11-13 13:21:23

标签: iphone objective-c memory-management object return-value

我弄乱了在方法中创建对象并将其返回给变量。和this post中一样,我知道在这种情况下我应该自动释放一个对象,但是当我这样做时,它会崩溃。

我编写了一个创建图像数组的方法,并返回此数组。它看起来像这样:

- (NSMutableArray *)createImagesFor:(NSString *)animName withFrames:(int)numberFrames {
    NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:numberFrames];
    for (int i = 1; i <= numberFrames; ++i) {
        NSString *imageName = [[NSString alloc]initWithFormat:@"%@%i.png", animName, i];
        [imageArray addObject:[UIImage imageNamed:imageName]];
        [imageName release];
    }
    return imageArray;
}

我称之为:

NSMutableArray *imageArray;
imageArray = [self createImagesFor:@"jumping" withFrames:2];
self.animationImages = imageArray;
[imageArray release];

但是,当我运行构建分析器时,它会进行编译,但会出现以下抱怨:

  

在第109行分配的物体的潜在泄漏   1.方法返回一个具有+1保留计数(拥有引用)的Objective-C对象   2.对象作为拥有引用返回给调用者(单个保留计数转移给调用者)
  3.在第109行分配的对象是从名称('createImagesFor:withFrames:')不包含'copy'或以'new'或'alloc'开头的方法返回的。这违反了“Cocoa内存管理指南”(对象泄露)

中给出的命名约定规则

我已经查看了memory management文档,但除了自动释放变量(崩溃了)之外,我不知道我哪里出错了。这是我自动释放它的方式:

NSMutableArray *imageArray = [[[NSMutableArray alloc] initWithCapacity:numberFrames]autorelease];

我尝试将* imageArray保留为suggested here,如下所示:

NSMutableArray *imageArray;
[imageArray retain];
    imageArray = [self createImagesFor:@"jumping" withFrames:2];
    self.animationImages = imageArray;
    [imageArray release];

但这也崩溃了。

分析器建议我将方法的名称更改为'newCreateImagesFor:withFrames:'但我不知道这是如何修复的?

感谢您的帮助。

迈克尔

2 个答案:

答案 0 :(得分:5)

您应该将第一个代码块的最后一行更改为return [imageArray autorelease]并在第二部分中删除该版本(通常不需要释放方法调用返回的对象)。这就是分析仪投诉的内容。但是,我不明白为什么它会导致崩溃。

如何定义animationImages属性?这可能是你问题的根源。

答案 1 :(得分:2)

    - (NSMutableArray *)createImagesFor:(NSString *)animName withFrames:(int)numberFrames {
    NSMutableArray *imageArray = [[NSMutableArray alloc] initWithCapacity:numberFrames];
    for (int i = 1; i <= numberFrames; ++i) {
        NSString *imageName = [[NSString alloc]initWithFormat:@"%@%i.png", animName, i];
        [imageArray addObject:[UIImage imageNamed:imageName]];
        [imageName release];
    }
    return imageArray;
}

返回一个保留计数为+1但未自动释放的imageArray对象,clang静态分析器会警告你这一点,这与命名约定有关,因为你的方法没有被命名与newImagesFor...allocImagesFor...copyImagesFor...相似。


NSMutableArray *imageArray;

[imageArray retain];
// sending message to nil, does nothing

imageArray = [self createImagesFor:@"jumping" withFrames:2];
// imageArray has a retain count of 1
// and it is an autoreleased object

self.animationImages = imageArray; 

[imageArray release]; 
// retain count = 0, will be dealloc'd, 
// however it is already in the autorelease pool, 
// it will be over-released at the end of current event run loop

当您声明imageArray时,它是指向类NSMutableArray的空指针,在您的情况retain中向Objective-C中的空指针发送消息是可能的,并且不会抛出异常。


如果使用属性访问器来缓存imageArray对象,则应声明属性访问器以保留您指定的对象

@property (retain) NSMutableArray *imageArray;

既然你的方法正确地返回了一个自动释放的imageArray,并且你有一个正确的属性访问器,那么所需要的只是

NSMutableArray *imageArray;
imageArray = [self createImagesFor:@"jumping" withFrames:2];
self.animationImages = imageArray;