释放新创建的对象时发生内存访问错误

时间:2009-12-31 15:00:22

标签: objective-c memory-management memory-leaks

我遇到了一个问题,理解为什么发布我刚刚创建的对象会导致我的应用程序出现内存访问错误。

我正在创建一堆对象并将它们添加到NSMutableArray中。将它们添加到数组后,我将它们释放出来。这个功能第一次运行,事情进展顺利。第二次运行该函数时,释放该对象会使应用程序崩溃,我不知道为什么。

以下是相关功能的一部分(完整项目源可在此处获取:http://github.com/cpjolicoeur/echowaves-notifier-osx

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [connection release];
    NSString *responseString = [[NSString alloc] initWithData:echowaves.responseData encoding:NSUTF8StringEncoding];
    [echowaves.responseData release];

    ...more code...

    [[echowaves updatedConvos] removeAllObjects];
    NSDictionary *dictionary = [responseString JSONValue];
    if ( [dictionary count] ) {
        for (NSDictionary *subscription in dictionary ) {
            UpdatedConvo *convo = [[UpdatedConvo alloc] initWithConvoName:[[subscription objectForKey:@"subscription"] objectForKey:@"convo_name"]
                                                                 convoURI:[[subscription objectForKey:@"subscription"] objectForKey:@"conversation_id"]
                                                              unreadCount:[[[subscription objectForKey:@"subscription"] objectForKey:@"new_messages_count"] integerValue]];


            [[echowaves updatedConvos] addObject:convo];
            [convo release];  // THIS LINE CAUSES CRASH 2ND TIME THROUGH
        }
    } else {

        ...more code....

    }
}            

应用程序第二次通过该功能在[convo release]行崩溃。由于convo对象在它之前创建了两行,我不知道为什么。

我的印象是UpdatedConvo *convo = [[UpdatedConvo alloc] initWithConvoName...]调用将创建对象并将其保留计数为1.然后,当我将对象添加到[echowaves updatedConvos] NSMutableArray对象时,它应该碰到保留计数为1(现在计数为2)。我已经完成了那个“临时”的convo对象,所以我然后释放它,它应该将其保留计数移回到1,正确??

我在这里缺少什么?

要让应用程序成功运行,我必须注释掉[convo release]行。我不知道为什么,我觉得这可能会给我一个缓慢的内存泄漏,因为新创建的UpdatedConvo对象没有正确地从内存中释放。

2 个答案:

答案 0 :(得分:3)

您的方法应该工作。创建对象,将其添加到字典,然后将其释放是一种常见模式。

它不起作用的事实表明问题出在其他地方。第一个要检查的地方是UpdatedConvo类本身。它的dealloc方法有什么特别之处吗?

编辑:问题肯定在UpdatedConvo。您使用=方法分配您的实例变量(init):

- (id)initWithConvoName:(NSString *)convoName
               convoURI:(NSString *)convoURI
            unreadCount:(int)updatesCount 
{
    if ( self = [super init] ) {
        ewURI = convoURI;
        ewName = convoName;
        newMessagesCount = updatesCount;
    }
    return self;
}

但是你在release

上打电话给dealloc
- (void)dealloc {
    [ewURI release];
    [ewName release];
    [super dealloc];
}

在init方法中使用=不会增加保留计数,因此当您释放它们时,实际上是将保留计数减少太多。

答案 1 :(得分:1)

正如e.James已经提到的:UpdatedConvo似乎是你的问题 我看了你发布的github项目。 可能你在UpdatedConvo中过度发布了:

- (void)dealloc 
{
    [ewURI release];
    [ewName release];
    [super dealloc];
}

您既没有创建,也没有在课堂上保留ewURI和ewName 所以你不应该在那里发布它。

<强>更新 修正了一个误导性错字(我在最后一句中写了“释放”而不是“保留”)

<强> UPDATE2: 我将使用“Zombie”和“Leaks”预设通过Instruments.app运行您的代码 如果您之前没有尝试过仪器,这是一个很好的机会,可以看到它在工作。