代码之家  ›  专栏  ›  技术社区  ›  cpjolicoeur

释放新创建的对象时出现内存访问错误

  •  1
  • cpjolicoeur  · 技术社区  · 15 年前

    我有一个问题,那就是为什么释放我刚创建的对象会在我的应用程序中导致内存访问错误。

    我正在创建一组对象,并将它们添加到一个非可变数组中。在我将它们添加到数组之后,我释放它们。函数第一次运行时,一切都很顺利。第二次函数运行时,释放对象会使应用程序崩溃,我不知道为什么。

    以下是相关功能的一部分(完整的项目源代码可在此处获得: 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] 在函数中第二次排列。因为护航对象是在它之前创建的两行,我不知道为什么。

    我觉得 UpdatedConvo *convo = [[UpdatedConvo alloc] initWithConvoName...] 调用将创建该对象,并将其保留计数设为1。然后当我将对象添加到 [echowaves updatedConvos] NSmutableArray对象,它应该将保留计数增加1(现在计数为2)。我已经处理完那个“临时”护航对象,所以我释放它,它的保留计数应该移回1,对吗??

    我这里缺什么?

    要使应用程序成功运行,我必须对[cavo release]行进行注释。但我不知道为什么,我觉得这可能会使我的内存泄漏变慢,因为新创建的updatedconvo对象没有从内存中正确释放。

    2 回复  |  直到 15 年前
        1
  •  3
  •   James Eichele Bernard Igiri    15 年前

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

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

    编辑: 问题肯定在 更新的会议 . 你 分配 您的实例变量(与 = 在你 init 方法:

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

    但是你打电话来 release 在他们身上 释放内存 :

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

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

        2
  •  1
  •   Thomas Zoechling    15 年前

    正如E.James已经提到的:更新的Convo似乎是您的问题。
    我看过你发布的Github项目。 可能您在updatedconvo中释放过度:

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

    您既没有在类中创建也没有保留ewuri和ewname。
    所以你不应该把它放在那里。

    更新: 修正了一个误导性的拼写错误(我在最后一句话中写了“释放”而不是“保留”)。

    更新2: 我会在instruments.app中运行带有“僵尸”和“泄漏”预设的代码。
    如果你以前没有试过乐器,这是一个很好的工作机会。