【问题标题】:iphone Memory Leak NSDictonaryiphone 内存泄漏 NSDictionary
【发布时间】:2011-09-11 06:08:04
【问题描述】:

我对 Objective-C 中的内存管理不是很熟悉,但我会尽力而为。几分钟后,我的应用程序崩溃了。在 Instruments 的帮助下,我发现了很多漏洞。有时我只是忘记释放对象或不将其放入自动释放池中。但是现在我真的不知道这种方法的问题出在哪里。 Instruments 显示 3 行泄漏。

感谢您的帮助。

- (NSMutableArray *)rowsFromTablePages {

NSString *sql = [NSString stringWithFormat:@"SELECT paid, creationdate, lastuseddate, image, background, backgroundid FROM Pages WHERE nsid=%i ORDER BY paid", _nsid];

sqlite3_stmt *statement;
NSMutableArray *allPages = [[[NSMutableArray alloc] init] autorelease];

  if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
      while (sqlite3_step(statement) == SQLITE_ROW) {
          int paid = (int)sqlite3_column_int(statement, 0);
          char *creationdate = (char *)sqlite3_column_text(statement, 1);
          char *lastuseddate = (char *)sqlite3_column_text(statement, 2);
          NSData *data = [NSData dataWithBytes:sqlite3_column_blob(statement, 3) length:sqlite3_column_bytes(statement, 3)]; // Leak
          NSData *databg = [NSData dataWithBytes:sqlite3_column_blob(statement, 4) length:sqlite3_column_bytes(statement, 4)]; // Leak
          int bgid = (int)sqlite3_column_int(statement, 5);

          NSDictionary *rowInArray = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:paid], @"PAID", [NSString stringWithUTF8String:creationdate], @"CREATIONDATE", [NSString stringWithUTF8String:lastuseddate], @"LASTUSEDDATE", [UIImage imageWithData:data], @"THUMBNAIL", [NSNumber numberWithInt:bgid], @"BGID", [UIImage imageWithData:databg], @"THUMBNAILBG", nil]; // Leak

          [allPages addObject:rowInArray];
      }
      sqlite3_finalize(statement);
  }
  return allPages;
}

Instruments 在同一个类中显示了调用此方法的泄漏。

- (void)reloadDataFromSQL {
    _dataSource = [[NSMutableArray alloc] initWithArray:[self rowsFromTablePages]]; // Leak
    [self.tableView reloadData];
}

【问题讨论】:

  • @HMMurdoc 它标记了哪些行?
  • 我在三行末尾写“// Leak”
  • @HMMurdoc 如果您省略了NSDictionary *rowInArray =...[allPages addObject:rowInArray]; 行,泄漏是否仍然存在?
  • 我不能将它们排除在外,因为如果没有数组,TabelView 将无法加载。我无法模拟它。另一个想法?!
  • 如果我错了,请纠正我,但我认为 Instruments 指向泄漏对象的分配,而不是对象的实际泄漏。由于您是通过allPages 间接返回这些对象,所以不会是其他任何地方的泄漏吗?

标签: iphone objective-c memory-leaks


【解决方案1】:

如果可行,试试这个.... if(_dataSource)

{

_dataSource =[self rowsFromTablePages];

}

否则 {

_dataSource = [[NSMutableArray alloc] initWithArray:[self rowsFromTablePages]]; // 泄漏

}

[self.tableView reloadData];

【讨论】:

    【解决方案2】:

    reloadDataFromSQL 方法中,您将新内存分配给NSMutableArray 的实例,而不释放任何内容。

    【讨论】:

    • 哦,那很痛苦...我添加了 '[_dataSource release];'在第一行'-(void)reloadDataFromSQL {...}'。泄漏已经消失了。谢谢大家!
    【解决方案3】:

    尝试使用+dataWithBytesNoCopy:length: 而不是-dataWithBytes:length:。这将确保字节不会被复制,这应该会阻止泄漏。

    【讨论】:

    • 在 +dataWithBytesNoCopy 中我不能使用 sqlite3_column_blob(statement, 3)。有什么想法吗?
    • dataWithBytes 需要一个“const void*”,dataWithBytesNoCopy 需要一个“void *”
    • 我不明白这将如何阻止泄漏,因为 NSData 的字节复制通常不会造成泄漏。而且由于 SQLite3 应该自动从sqlite3_column_blob() 中获取内存,我认为这会导致双重释放。我错过了什么吗?
    【解决方案4】:

    你运行了多少次 while 循环?我怀疑可能是自动释放池超载并产生内存错误。尝试在 while 循环之外声明变量并手动释放它们。让我知道它是如何工作的。

    【讨论】:

    • 循环运行了 3 次,因为我的数据库中有 3 行。我会尝试在外面声明变量。
    猜你喜欢
    • 2011-11-08
    • 2011-05-20
    • 1970-01-01
    • 2010-11-23
    • 2011-12-10
    • 2011-05-24
    • 2023-03-20
    相关资源
    最近更新 更多