NSArray对于超出范围的对象非常奇怪

时间:2010-03-25 20:46:36

标签: objective-c memory-management nsarray

我对NSArray有一些奇怪的问题,我的数组中某些对象的成员超出了范围而不是其他成员:

我有一个名为Section的简单对象。 它有3名成员。

@interface Section : NSObject {
    NSNumber *section_Id;   
    NSNumber *routeId;
    NSString *startLocationName;
}
@property(nonatomic,retain)  NSNumber *section_Id;  
@property(nonatomic,retain)  NSNumber *routeId;
@property(nonatomic,retain)  NSString *startLocationName;
@end


@implementation Section

@synthesize section_Id; 
@synthesize routeId;
@synthesize startLocationName;

//Some static finder methods to get list of Sections from the db
+ (NSMutableArray *) findAllSections:{


- (void)dealloc {
    [section_Id release];
    [routeId release];
    [startLocationName release];

    [super dealloc];
}

@end

我在一个名为findAllSection

的方法中从数据库中填充它
self.sections = [Section findAllSections];

在查找所有部分时,我创建了一些局部变量,用db。中的数据填充它们。

NSNumber *secId = [NSNumber numberWithInt:id_section];
NSNumber *rteId = [NSNumber numberWithInt:id_route];
NSString *startName = @"";

然后创建一个新的Section并将这些局部变量的数据存储在Section

Section *section = [[Section alloc] init];

section.section_Id = secId;
section.routeId = rteId;
section.startLocationName = startName;

然后我将该部分添加到数组

[sectionsArray addObject:section];

然后我清理,释放局部变量和我添加到数组的部分     [secId release];     [rteId发布];     [startName release];     [locEnd_name release];

[section release];

在循环重复所有章节(释放局部变量,并在每个循环中完成部分)

该方法返回并检查数组,所有部分都在那里。我似乎无法深入挖掘数组中的Section对象的值(这是可能的)

稍后我尝试检索其中一个部分

我是从数组中得到的

Section  * section = [self.sections objectAtIndex:row];

然后检查值

NSLog(@" SECTION SELECTED:%@",section.section_Id);

但是对section.section_Id的调用因section.section_Id而崩溃超出了范围。

我检查了这个Section对象的其他成员,他们没问题。 经过一些试验和错误后,我发现通过注释掉成员变量的释放,对象就可以了。

//[secId release];
[rteId release];
[startName release];
[locEnd_name release];


[section release];

我的问题是:

我清理好吗?

我应该释放添加到数组的对象和函数中的局部变量吗?

我的dealloc是否在分区?

这段代码看起来不错吗?我应该在别处寻找问题吗?

我没有做任何复杂的事情,只需从DB填充数组就可以在Table Cell中使用它。

我可以评论该版本,但我更愿意知道为什么这样做,如果我不应该这样做。 secId被释放的唯一地方是dealloc。

3 个答案:

答案 0 :(得分:4)

您不应该发布secIdrteIdstartNamesecIdrteId是使用返回已经自动释放的对象的工厂方法创建的NSNumber实例的指针。不需要释放静态字符串(即@"")。您需要重新阅读Memory Management Programming Guide。然后再读一遍;-)这将是你的朋友。

答案 1 :(得分:3)

您正在发布您不拥有的对象。您应该阅读memory management rules

答案 2 :(得分:2)

我将第二个(第三个)建议阅读内存管理规则。

TL; DR版本是您alloc的任何内容,并且在方法名称中使用init调用方法是您有责任发布的。例如:

NSString *string = [[NSString alloc] initWithFormat:@"%@", someObject];

在这种情况下,您必须释放string。但是:

NSString *string = [NSString stringWithFormat:@"%@", someObject];

此处string已自动释放。它基本上等同于:

NSString *string = [[[NSString alloc] initWithFormat@"%@", someObject] autorelease];

...意味着下一次通过事件循环(这意味着可能一旦函数返回),系统将为您发送release消息。 Apple将这些称为“便利方法”。

如果你有这样的事情:

NSString *string = @"foo";

然后string指向NSString的一个实例,该实例是在程序初始化时由运行时创建的,并且在程序终止之前不会超出范围。从来没有release这些。

再次阅读指南并将其加入书签。但这应该回答你的直接问题。