ARC и повторное использование указателей исчерпывает память - PullRequest
0 голосов
/ 16 декабря 2011

Мне показалось, что я держу голову над удержаниями и выпусками до тех пор, пока не будет реализована 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 ]

4 голосов
/ 16 декабря 2011

Старая концепция управления памятью по-прежнему верна, что автоматически выпущенные экземпляры в глобальном пуле релизов не будут освобождены до завершения текущего цикла выполнения, с или без ARC.

Если вы пишете нетривиальную итерацию, например тысячиитерация, обертывание с пулом авто-релиза - путь.Вы можете использовать

@autoreleasepool {
    // your code here
}

для упрощения использования.Нет ничего плохого или неидеального в использовании пула автоматического выпуска, так как он был там по какой-то причине.ARC, как следует из названия, выполняет только автоматический подсчет ссылок.Задача управления использованием памяти по-прежнему принадлежит нам.

0 голосов
/ 16 декабря 2011

Я попробовал ваш пример.Никаких утечек, абсолютно нет: ни на iOS5 ни в приложении, ни в настольном приложении.Также проверено в инструментах.(Xcode 4.2.1, сборка 4D502, скомпилированная с LLVM 3.0)

...