ARC和重新使用指针会耗尽内存

时间:2011-12-16 14:36:41

标签: objective-c ios automatic-ref-counting

我认为在ARC实施之前我一直保留并发布,我倾向于尝试重用指针以节省必须一直重新声明它们。

但是使用ARC,它会造成泄漏。我的猜测是它只释放分配给'tmp'指针的最后一个对象,我假设当我给指针一个新对象时,旧对象会自动释放。在autoreleasepool中包装该函数似乎可以完成这项工作,但这真的是理想的解决方案还是我的编码风格错了?

这是一个有罪的功能,在我运行几百次后似乎吃掉了我的所有内存:

- (void) saveJDictEntry:(JDictEntry *)entry {

  const char * query;
  char * errMsg;
  NSString *queryString;    
  sqlite3_stmt * statement;

  [self connect];   

  // Insert the word..
  queryString = [NSString stringWithFormat:@"INSERT INTO words (seq) VALUES (%i)", entry.number];
  query = [queryString UTF8String];
  if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
      NSLog(@"Statement failed %@ %@", errMsg, queryString);
  }


  // Get the last id we inserted..
  NSUInteger lastId = 0;
  queryString = @"SELECT last_insert_rowid()";
  query = [queryString UTF8String];
  sqlite3_prepare_v2(database, query, -1, &statement, NULL);    
  if (sqlite3_step(statement) == SQLITE_ROW) {
      lastId =  sqlite3_column_int(statement, 0);
  } else {
      NSLog(@"Failed to fetch last Id after saving");        
  }
  sqlite3_finalize(statement);    

  entry.databaseId = lastId;
  entry.saved = true;



  // Kana...
  queryString = [NSString stringWithFormat:@"INSERT INTO words_kana (word_id, kana) VALUES (%i, '%@')", entry.databaseId, entry.kana ];
  query = [queryString UTF8String];    
  if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
      NSLog(@"Statement failed %@ %@", errMsg, queryString);
  }        

  // Kanji ...
  for(NSString * _kanji in entry.kanji) {
      queryString = [NSString stringWithFormat:@"INSERT INTO words_kanji (word_id, kanji) VALUES (%i, '%@')", entry.databaseId, _kanji];
      query = [queryString UTF8String];    
      if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
          NSLog(@"Statement failed %@ %@", errMsg, queryString);
      }              
  }

  // Pos..
  for(NSString * _pos in entry.pos) {
      queryString = [NSString stringWithFormat:@"INSERT INTO words_pos (word_id, pos) VALUES (%i, '%@')", entry.databaseId, _pos];
      query = [queryString UTF8String];    
      if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
          NSLog(@"Statement failed %@ %@", errMsg, queryString);
      }              
  }

  // Gloss
  for(NSString * _gloss in entry.gloss) {
      NSString * glossField = [_gloss stringByReplacingOccurrencesOfString:@"'" withString:@"''"];            
      queryString = [NSString stringWithFormat:@"INSERT INTO words_gloss (word_id, gloss) VALUES (%i, '%@')", entry.databaseId, glossField];
      query = [queryString UTF8String];    
      if (sqlite3_exec(database, query, NULL, NULL, &errMsg) != SQLITE_OK) {
          NSLog(@"Statement failed %@ %@", errMsg, queryString);
      }              
  }   


}

2 个答案:

答案 0 :(得分:4)

旧的内存管理概念仍然适用于全局发布池中的自动释放实例在完成当前运行循环之前不会释放,无论是否有ARC。

如果您正在编写非平凡的迭代,例如数千次迭代,用自动释放池包装它是要走的路。你可以使用

@autoreleasepool {
    // your code here
}

简化用法。使用自动释放池没有任何错误或不理想,因为它出于某种原因存在。顾名思义,ARC只进行自动引用计数。管理内存使用的任务仍属于我们。

答案 1 :(得分:0)

我尝试了你的例子。没有泄漏,绝对不是:iOS5应用程序和桌面应用程序都没有。还检查了仪器。 (Xcode 4.2.1,Build 4D502,使用LLVM 3.0编译)