【问题标题】:Objective C Leaks memory on Autoreleased ObjectObjective C 在自动释放的对象上泄漏内存
【发布时间】:2011-10-16 06:02:11
【问题描述】:

好的,我知道有很多关于这个问题的问题,但是在阅读它们并尝试了这些方法之后,我的应用程序似乎仍然泄漏内存。我研究了Apple Guide on Memory Manegment 并阅读了值得注意的问题hereherehere。我有一个解析 JSON 字符串然后将它们返回到NSMutableDictionary 的方法。我从返回方法对对象调用autorelease,然后在接收方法上调用retain(确保对象在池的下一个排水管上不释放)。然后当我完成它时我释放然后对象。但是它仍然泄漏。谁能看到我做错了什么?

返回方法

+ (NSMutableArray *)parseSpecialtyResult:(NSString *)json
{
    SBJsonParser *parser = [[SBJsonParser alloc] init];

    NSDictionary *dictionary = [parser objectWithString:json];

    NSArray *jsonObjects = [dictionary valueForKey:@"Rows"];

    NSMutableArray *jsonArray = [[NSMutableArray alloc] initWithCapacity:[jsonObjects count]];

    //Storing objects
    for (NSDictionary *dict in jsonObjects) 
    {
        Specialty *specialty = [[Specialty alloc] init];
        [specialty setName:[dict objectForKey:@"name"]];
        [specialty setIdenity:[dict objectForKey:@"id"]];

        [jsonArray addObject:specialty];
    }

    [parser release];

    //Relinquish ownership of this object
    return [jsonArray autorelease];
}

调用类

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [connection release];

    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
    [responseData release];

    //This class will take the responsibility of the object's ownership
    self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];

    [tableView reloadData];

    [responseString release];
}

- (void)dealloc
{
    [super dealloc];
    //No longer need the object
    [jsonArray release];
    NSLog(@"Ref count %i", [jsonArray retainCount]);
}

日志

Ref count 1

【问题讨论】:

  • 还要注意,retainCount 对于查看这类事情几乎是一种无用的方法。在这里搜索它,你会看到 bbum 经常谈论它。 (而且他应该知道他在 Apple 工作的地方。)
  • 通常retainCount 不显示真实信息。如果你想检查,你的内存在哪里增长,使用仪器。顺便说一句,你可以 1)释放你的专长,这可能会导致泄漏。
  • @Grant 感谢您提供的信息。我在分析器中仔细检查了它,并确认它正在泄漏:(
  • 您是否从 Xcode 4 的 Product 菜单中运行了 Analyze?它实际上非常擅长查找并向您展示发生泄漏和过度发布的位置。

标签: iphone objective-c ios memory-management autorelease


【解决方案1】:

您没有释放forstatement 中的Speciality 对象:

for (NSDictionary *dict in jsonObjects) 
{
    Specialty *specialty = [[Specialty alloc] init];
    ...
    [jsonArray addObject:specialty];
    [specialty release];
}

另外,如果jsonArray 是一个保留或复制属性,这会过度保留对象:

self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];

应该是简单的(同样,如果保留或复制):

self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];

另外,[super dealloc]; 应该是dealloc 中的最后一条语句。

【讨论】:

  • 他还保留了[SpecialtyUrl parseSpecialtyResult:responseString]。他不应该那样做(假设jsonArray(nonatomic, retain) 属性)。
  • 好的,但是由于仍然存在对 NSMutableArray 的引用,因此数组的内容仍然被保留和泄露。
  • 我在 [jsonArray release] 线上得到一个 EXC_BAD_ACCESS;
  • @Sbossb 你把[super dealloc] 放在[jsonArray release] 后面了吗? ]您是否进行了我建议的所有其他更改? jsonArray 是如何声明的?是合成的吗?
【解决方案2】:

你在这条线上泄露了:

Specialty *specialty = [[Specialty alloc] init];

你创造了一堆专业,但你从未发布它们。

在这一行中,您通过在前面使用 self 来过度保留对象 jsonArray。

self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];

因为您可能将 jsonArray 属性声明为:

@property(nonatomic,retain)...

然后你合成了它。它为您创建了一个 setter,当您使用 self 分配对象时,它会保留一个对象。

所以

self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];

够了。

【讨论】:

    【解决方案3】:

    假设 jsonArray 是调用类的 retain 属性,您将添加一个额外的保留:

    self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
                                                                            ^ 
                                                                       Right here!
    

    setter 应该已经正确地保留和释放。所以保留在那里只会泄漏对象。

    您需要释放专业对象的其他答案也是正确的。但是,只要您过度保留 Specialty 对象所在的数组,泄漏就会一直存在。

    【讨论】:

      【解决方案4】:

      当您在这里取得对象的所有权时,您可能会收到两条保留消息。

       //This class will take the responsibility of the object's ownership
       self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
      

      如果 jsonArray 属性声明为 (retain) 或 (nonatomic, retain)。简单地将 jsonArray 分配给属性将导致发送保留。您可以将代码更改为:

      > @property (nonatomic, retain) NSMutableArray  *jsonArray;
      > 
      > @synthesize jsonArray;
      > 
      > self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];
      

      【讨论】:

        猜你喜欢
        • 2011-04-27
        • 1970-01-01
        • 2012-06-13
        • 2010-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-25
        • 1970-01-01
        相关资源
        最近更新 更多