为什么这段代码没有泄漏?

时间:2010-12-05 17:39:36

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

我是开发新手,无法解决这个问题:

 for(NSString *collectionName in jsonObjects)
  {
    NSDictionary *collection = [[NSDictionary alloc] init];
    collection = [jsonObjects valueForKey:collectionName];
    NSArray *items = [[NSArray alloc] initWithArray:[collection valueForKey:@"items"]];
    NSNumber *lastAccess = [[NSNumber alloc] init];

    lastAccess = [collection valueForKey:@"lastAccess"];

    [items release];
  }

我不明白为什么会这样,当我发布 lastAccess 集合时,程序崩溃并出现EXC_BAD_ACCESS错误...但是如果我不赞成发布项目我收到了泄密。任何人都可以说清楚这一点。我认为如果你使用alloc,那么你拥有引用,因此必须释放?

4 个答案:

答案 0 :(得分:4)

该代码存在许多问题。暂时忽略基金会缓存某些常用值。

这种模式毫无意义:

NSDictionary *collection = [[NSDictionary alloc] init];
collection = [jsonObjects valueForKey:collectionName];

第一行创建一个(空)NSDictionary实例,第二行立即覆盖对它的引用。泄漏和完全没有意义;第一行不需要分配/分配。同样适用于lastAccess

由于第二行返回了一个非拥有的引用,尝试release它会导致崩溃。

请注意如果发生崩溃,则会有回溯。这个问题很简单,不需要,但总是寻找回溯线索。

请注意,您实际上不会看到NSNumberNSDictionary实例的泄漏,因为基金会恰好有单例。在NSNumber案例​​中它只是没有意义。但是,空字典经常被使用,并且单个字节可以节省内存。

答案 1 :(得分:1)

for(NSString *collectionName in jsonObjects)
{
  NSDictionary *collection = [[NSDictionary alloc] init]; // Allocation 
  collection = [jsonObjects valueForKey:collectionName]; // overwriting above, LEAKS
  NSArray *items = [[NSArray alloc] initWithArray:[collection valueForKey:@"items"]]; // Allocation
  NSNumber *lastAccess = [[NSNumber alloc] init]; // Allocation
  lastAccess = [collection valueForKey:@"lastAccess"]; // overwriting above, LEAKs
  [items release];
}

不包含'alloc'或'new'的调用返回对'autoreleased'对象的引用,这意味着它们不归你所有,释放它们会导致崩溃。您可以使用它们,但仅限于您所在功能的范围,如果您需要它们供以后使用,则需要在它们上面调用retain。因此,在调用访问器函数时,您只需要声明所需的变量,而不是创建新对象。

alloc创建一个新对象,在collection的情况下,您创建一个空的NSDictionary,但是您使用自动释放的引用快速覆盖对该新对象的引用valueForKey:这会造成泄密。由于最初创建的对象不会被释放。

可能看起来像这样

for(NSString *collectionName in jsonObjects)
{
  NSDictionary *collection = [jsonObjects valueForKey:collectionName];
  NSArray *items = [collection valueForKey:@"items"];
  NSNumber *lastAccess = [collection valueForKey:@"lastAccess"];
}

我意识到,有了这样的问题的能力,一个自愿的人群回答阅读手册已经成为一件苦差事但如果你想要进步你应该看看,大多数苹果文档都写得非常好,因为这些事情发生了。 memory management guide将解决很多问题。

答案 2 :(得分:0)

在该代码中,您只需重新分配lastAccess指针,这会导致alloc编辑NSNumber泄露。您需要实际设置NSNumber指向的lastAccess对象的值。

编辑:

我已经放了一些示例代码,但是我把它拿出来,因为我现在意识到上面的代码示例有太多问题。请查看NSDictionary的文档。使用collection,您将创建一个对象,然后通过将其指针重新指定给其他对象来泄漏它。一旦你解决了这些问题,我建议用新代码更新问题。

答案 3 :(得分:0)

在上面的@bbum之后,我会写这样的代码:

for(NSString *collectionName in jsonObjects)
{
NSDictionary *collection = [jsonObjects valueForKey:collectionName];
NSArray *items = [NSArray arrayWithObject:[collection valueForKey:@"items"]];
NSNumber * lastAccess = [collection valueForKey:@"lastAccess"];
}

在这种情况下,所有变量都将自动释放,因此您无需手动释放它们。