2011-10-14 2 views
2

나는 그것을 고치려고 몇 시간을 보냈지만 방금 포기했습니다. 나는 무엇이 잘못되었는지 전혀 모른다.iOS 메모리 문제의 Sqlite

내 응용 프로그램에서 내 모든 개체를 올바르게 설정하려면 중첩 된 SQL 작업을 수행합니다. 어떤 이유로 sqlite3 객체가 제대로 해제되지 않아 메모리가 지붕 위로 올라 가게됩니다. 올바르게 sql3_close 및 sql3_finalize를 사용하는 것이 문제라는 것을 알고 있습니다. 그러나 보시다시피, 나는 그들이 올바르게 사용했다고 생각합니다. 나는 정확히 같은 사용, 메모리를 엉망으로 사람에 따라서

- (IndoorLocation *) getIndoorLocationWithId:(NSNumber *) locId { 
    if (sqlite3_open([databasePath UTF8String], &db) == SQLITE_OK) { 
     if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK) { 
      while (sqlite3_step(statement) == SQLITE_ROW) { 
       //if I comment the thing below it works 
       NSNumber *_id = [[NSNumber alloc] initWithInt:(int) sqlite3_column_int(statement, 5)]; 
       toReturn.outLoc = [self getOutdoorLocationWithId:_id]; 
       [_id release]; 

      } 
      sqlite3_finalize(statement); 
     } 
     sqlite3_close(db); 
    } 
} 

: 메모리를 엉망으로 한 그래서 여기

- (NSArray *) getAllSessions { 
    if (sqlite3_open(dbPath, &db) == SQLITE_OK) { 
     if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK) { 
      while (sqlite3_step(statement) == SQLITE_ROW) { 

       //I found out that doing something like that 
       //toAdd.in_loc = [self getIndoorLocationWithId:[NSNumber numberWithInt:(int)sqlite3_column_int(statement, 6)]]; 
       //messes the memory up all the time 
       //but doing that works OK: 
       NSNumber *_id = [[NSNumber alloc] initWithInt:(int) sqlite3_column_int(statement, 5)]; 
       toAdd.out_loc = [self getOutdoorLocationWithId:_id]; 
       [_id release]; 

       //So I did the same with the second one, but this one messes memory up: 
       NSNumber *id2 = [[NSNumber alloc] initWithInt:(int)sqlite3_column_int(statement, 6)]; 
       toAdd.in_loc = [self getIndoorLocationWithId:id2]; 
       [id2 release]; 
      } 
      sqlite3_finalize(statement); 
     } 
     sqlite3_close(db); 
    } 
} 

됩니다 : 여기

는 문제의 원인 함수가 처음으로 (getOutdoorLocationwithId) 같은 방식으로 작동하지만 작동하지 않으면 sqlite3 객체가 제대로 해제되지 않습니다.

내 문제를 이해하시기 바랍니다.

+0

데이터베이스가 이미 getAllSessions에서 열리고 다시 열리고 닫히면 데이터베이스가 엉망입니다. 두 가지 방법 모두에서 반환 유형을 선언하지만 아무 것도 반환하지 않습니다. xcode가이 문제에 대해 불평하지 않습니까? –

+0

간단하게 유지하기 위해 모든 코드를 포함하지 않았습니다. 귀하의 첫 번째 요점에 관해서, 나는 동의하지만, 왜 그것이 처음이 아니라 두 번째가 작동합니까? – chopchop

답변

3

이와 같은 단일 사용자 앱에서는 지속적으로 열거 나 닫을 필요가 없습니다. 이것은 연결을 유지하면 풀을 무너 뜨릴 수 있고 확장 성을 손상시킬 수있는 여러 사용자와 연결 풀이있는 서버 기반 응용 프로그램과 다릅니다. 전화 응용 프로그램에서 열어서 열어 두십시오. 완료되면 닫으십시오. 최소한 재귀 호출 내에서 그렇게하십시오.

재귀 호출을 열면 닫히기 때문에 열어두면됩니다. 또한

:

  • 당신은
  • 당신은 주변의 반환 코드를 확인하지 않는 마무리의 반환 코드를 검사 한 아닙니다.
  • 문장을 준비 (컴파일)하고 있지만 저장하지 않고 있습니다. 저장된 문장에서 재설정을 실행하고 다시 실행하십시오.

FMDB 사용을 고려해보십시오. 좋은 포장지입니다.

여기가 더 풍부하고 내구성이 우수하지만 모든 통화에서 사용하지 마십시오. 끝나거나 앱이 백그라운드로 들어갈 때 닫습니다 ... 이것은 fmdb가하는 것과 유사한 내 것입니다.

- (void)close 
{ 
    if (_sqlite3) 
    { 
     ENInfo(@"closing"); 
     [self clearStatementCache]; 

     int rc = sqlite3_close(_sqlite3); 
     ENDebug(@"close rc=%d", rc); 

     if (rc == SQLITE_BUSY) 
     { 
      ENError(@"SQLITE_BUSY: not all statements cleanly finalized"); 

      sqlite3_stmt *stmt; 
      while ((stmt = sqlite3_next_stmt(_sqlite3, 0x00)) != 0) 
      { 
       ENDebug(@"finalizing stmt"); 
       sqlite3_finalize(stmt); 
      } 

      rc = sqlite3_close(_sqlite3); 
     } 

     if (rc != SQLITE_OK) 
     { 
      ENError(@"close not OK. rc=%d", rc); 
     } 

     _sqlite3 = NULL; 
    } 
} 
+0

굉장한 개폐 시간이 항상 문제였습니다. 정말 고마워요! – chopchop

0

나는이 문제를 만났다. FMDB를 사용하고 열 때 제대로 작동합니다. 다른 콜백에서는 실패하고 "누출 된 문을 닫음"예외를 던졌습니다. 마지막으로 나는 [FMDatabase databaseWithPath : dbPath]에서 포인터를 유지했기 때문에 포인터가 autorelease 객체라는 것을 알았습니다. 나는이에 의한 문제 해결 :

FMDatabase *db = [[FMDatabase databaseWithPath:dbPath] retain]; 

및 데이터베이스 종료 할 때 : DB를 [닫기] [db release]; db = nil;

이렇게하면 각 작업에 대해 항상 데이터베이스를 열고 닫을 필요는 없으며 데이터베이스를 관리하는 관리자 개체 여야합니다. 관리자가 시작되면 데이터베이스는 항상 관리자가 중지 할 때까지 열립니다.