2009-01-23 53 views
2

我通过Cocoa Programming for Mac OS X (3rd ed)并在第4章的工作,我写这个程序:示例可可应用程序,ref计数,[pool drain]产生EXC_BAD_ACCESS?

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    //create the date object 
    NSCalendarDate *now = [[NSCalendarDate alloc] init]; 

    //seed random # generator 
    srandom(time(NULL)); 

    NSMutableArray *array; 
    array = [[NSMutableArray alloc] init]; 
    int i; 
    for (i=0; i<10; i++){ 
     //create a date/time that is 'i' weeks from now 
     NSCalendarDate *iWeeksFromNow; 
     iWeeksFromNow = [now dateByAddingYears:0 
             months:0 
              days:(i*7) 
             hours:0 
             minutes:0 
             seconds:0]; 

     //create a new instance of lottery entry 
     LotteryEntry *entry = [[LotteryEntry alloc] init]; 
     [entry setEntryDate:iWeeksFromNow]; 

     [array addObject:entry]; 
     [entry release]; 
    } 
    [now release]; 
    now = nil; 

    for (LotteryEntry *entryToPrint in array) { 
     NSLog(@"%@", entryToPrint); 
    } 
    [array release]; 
    array = nil; 

    NSLog(@"about to drain the pool... (%@)", pool); 
    [pool drain]; 
    NSLog(@"done"); 
    NSLog(@"GC = %@", [NSGarbageCollector defaultCollector]); 
    return 0; 
} 

的LotteryEntry类看起来是这样的:

@implementation LotteryEntry 

- (void)setEntryDate:(NSCalendarDate *)date 
{ 
    entryDate = date; 
} 

- (NSCalendarDate *)entryDate 
{ 
    return entryDate; 
} 

- (int)firstNumber 
{ 
    return firstNumber; 
} 

- (int)secondNumber 
{ 
    return secondNumber; 
} 

- (id)init 
{ 
    return [self initWithDate:[NSCalendarDate calendarDate]]; 
} 

- (id)initWithDate:(NSCalendarDate *)date 
{ 
    if(![super init]) 
     return nil; 

    NSAssert(date != nil, @"Argument must be non-nil"); 

    firstNumber = random() % 100 + 1; 
    secondNumber = random() % 100 + 1; 
    entryDate = [date retain]; 
    return self; 
} 

- (NSString *)description 
{ 
    NSString *result; 
    result = [[NSString alloc] initWithFormat:@"%@ = %d and %d", 
       [entryDate descriptionWithCalendarFormat:@"%b %d %Y"], 
       firstNumber, 
       secondNumber]; 
    return result; 
} 

- (void)dealloc 
{ 
    NSLog(@"deallocating %@", self); 
    [entryDate release]; 
    [super dealloc]; 
} 

@end 

正如你可以看到我保持和释放对象这里。我敢肯定我的代码相匹配的书的,但是当我运行应用程序,在[池漏]我得到这个消息:

程序接收到的信号: “EXC_BAD_ACCESS”。

我不确定是什么原因造成的。我希望这是我错过的一些愚蠢的东西,但是我一定会欣赏其他几双眼睛。提前致谢!

(旁注:我是一个.NET开发人员,所以裁判的计数是相当陌生的我)

+0

就像说明一样,您应该使用NSDate,而不是NSCalendarDate。 – 2009-01-23 16:44:26

回答

2

卫生署!只要输入代码就可以让我意识到我的问题。当这种情况发生时,Doncha喜欢它吗?

我保留在我的init中的日期,但我仍然有那个额外的setEntryDate方法没有调用retain。删除这个并调用initWithDate方法反而似乎解决了这个问题。

1

这与您手边的问题无关,但您应该避免使用NSCalendarDate,它现在已被弃用,并且可能很快就会从API中删除。

+1

什么是替代? – 2009-02-04 14:50:02

+0

NSCalendar,NSDate和NSDateComponents。您可以在这里阅读更多关于它们的信息:http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/DatesAndTimes/Articles/dtCalendars.html – 2009-02-04 15:51:30

3

它也像你在这个方法中的错误:

- (id)initWithDate:(NSCalendarDate *)date 
{ 
    if(![super init]) 
     return nil; 

    NSAssert(date != nil, @"Argument must be non-nil"); 

    firstNumber = random() % 100 + 1; 
    secondNumber = random() % 100 + 1; 
    entryDate = [date retain]; 
    return self; 
} 

你基本上是丢弃来自[超级初始化]的结果,而这可能不是在这种情况下的一个问题,它可能会导致严重在别人遇到问题。你应该“总是”的结构,你的init方法是这样的:

- (id)initWithDate:(NSCalendarDate *)date 
{ 
    if(self = [super init]) { 
     NSAssert(date != nil, @"Argument must be non-nil"); 

     firstNumber = random() % 100 + 1; 
     secondNumber = random() % 100 + 1; 
     entryDate = [date retain]; 
} 
return self; 

如果你不打算从init方法(例如它是一个工厂或一些奇怪的类似),你应该记住释放回归自我自。它已经被分配,如果你不返回它,它不能被正确释放。例如:

- (id) init 
{ 
    NSObject* newSelf = [[NSObject alloc] init]; 

    [self release]; 
    return newSelf; 
} 
相关问题