2015-08-26 12 views
6

Ricevo perdite di memoria su sqlite3_open anche se sqlite_close, sqlite3_finalize sono applicate, per favore guidami dove sto andando male. Il progetto è in non - ARC.Objective C - sqlite3_open Perdita di memoria anche se sqlite3_close() applicata

 -(BOOL)saveMedia:(NSDictionary *)details Download:(NSInteger)completed 
{ 
    //NSLog(@"media savemedia %@",[details objectForKey:@"type"]); 
    BOOL saved = FALSE; 
    NSInteger exists = [self findMedia:[details objectForKey:@"media_id"] playlist_id:[details objectForKey:@"playlist_id"] type:[details objectForKey:@"type"]]; 
    sqlite3_stmt *statement; 

    self.databasePath = [self getDBPath]; 
    const char *dbpath = [databasePath UTF8String]; 
    if (sqlite3_open(dbpath, &wazzupco) == SQLITE_OK) 
    { 
     const char *query_stmt; 
     if (exists == 0) 
     { 
      query_stmt = "INSERT INTO media (media_id, title, description, file, views, thumbnail, version, playlist, playlist_id, author, created_at, type, playlist_created, timeout, playlist_order, media_order, playlist_promo_text, playlist_promo_url, playlist_promo_img,video_promo_text, video_promo_url, video_promo_img, dev_id, device_id, downloaded,slide_timeout) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 
     } 
     else if([[details objectForKey:@"version"] integerValue] > exists) 
     { 
      NSString *querySQL = [NSString stringWithFormat:@"UPDATE %@ SET media_id=?, title=?, description=?, file=?, views=?, thumbnail=?, version=?, playlist=?, playlist_id=?, author=?, created_at=?, type=?, playlist_created=?, timeout=?, playlist_order=?, media_order=?, playlist_promo_text=?, playlist_promo_url=?, playlist_promo_img=?,video_promo_text=?, video_promo_url=?, video_promo_img=?, dev_id=?, device_id=?, downloaded=?, slide_timeout=? WHERE media_id='%@' AND playlist_id='%@' AND type='%@'", TABLE_MEDIA, [details objectForKey:@"media_id"], [details objectForKey:@"playlist_id"], [details objectForKey:@"type"]]; 
      query_stmt = [querySQL UTF8String]; 
     } 
     else 
     { 
      //to make sure we won't update the database entry unless its a newer version 
      return FALSE; 
     } 
     sqlite3_prepare_v2(wazzupco, query_stmt, -1, &statement, NULL); 

     sqlite3_bind_text(statement, 1, [[details objectForKey:@"media_id"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 2, [[details objectForKey:@"title"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 3, [[details objectForKey:@"description"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 4, [[details objectForKey:@"file"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 5, [[details objectForKey:@"views"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 6, [[details objectForKey:@"thumbnail"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 7, [[details objectForKey:@"version"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 8, [[details objectForKey:@"playlist"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 9, [[details objectForKey:@"playlist_id"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 10, [[details objectForKey:@"author"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 11, [[details objectForKey:@"created_at"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 12, [[details objectForKey:@"type"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 13, [[details objectForKey:@"playlist_created"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 14, [[details objectForKey:@"timeout"] UTF8String], -1, NULL); 
     sqlite3_bind_int(statement, 15, [[details objectForKey:@"playlist_order"] intValue]); 
     sqlite3_bind_int(statement, 16, [[details objectForKey:@"media_order"] intValue]); 
     sqlite3_bind_text(statement, 17, [[details objectForKey:@"playlist_promo_text"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 18, [[details objectForKey:@"playlist_promo_url"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 19, [[details objectForKey:@"playlist_promo_img"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 20, [[details objectForKey:@"video_promo_text"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 21, [[details objectForKey:@"video_promo_url"] UTF8String], -1, NULL); 
     sqlite3_bind_text(statement, 22, [[details objectForKey:@"video_promo_img"] UTF8String], -1, NULL); 
     sqlite3_bind_int(statement, 23, [[details objectForKey:@"dev_id"] intValue]); 
     sqlite3_bind_text(statement, 24, [[details objectForKey:@"device_id"] UTF8String], -1, NULL); 
     sqlite3_bind_int(statement, 25, (int)completed); 
     sqlite3_bind_text(statement, 26, [[details objectForKey:@"slide_timeout"] UTF8String], -1, NULL);   
     if (sqlite3_step(statement) == SQLITE_DONE) 
     { 
      NSLog(@"media added. type:%@",[details objectForKey:@"type"]); 
      saved = TRUE; 
     } 
     sqlite3_finalize(statement); 
     //sqlite3_free(statement); 
     //sqlite3_reset(statement); 
    } 
    sqlite3_close(wazzupco); 
    if (completed != 0 && saved) 
    { 
     [self updateMediaStatus:[details objectForKey:@"file"] Download:1]; 
    } 

    return saved; 
} 

Nel codice precedente sto di inserire o aggiornare dati da una NSDictionary alla tavola sqlite considerando se i dati esistono già o meno. Il metodo viene eseguito correttamente ma produce gravi perdite di memoria (il metodo viene chiamato più volte da un ciclo), quando viene selezionato in Strumento mostra che la perdita è in if (sqlite3_open (dbpath, & wazzupco) == SQLITE_OK).

Da strumento

oggetto trapelato: Malloc 64bytes

Indirizzo Dimensioni: 1.12KB Biblioteca Responsabile: libsqlite3.dylib Responsabile Telaio: 0x34bdce30

+0

Perché stai ignorando 'sqlite3_prepare_v2()' 's codice di ritorno? –

+0

@CL. Dovrei aggiungere una condizione, se (sqlite3_prepare_v2 (wazzupco, query_stmt, -1, & statement, NULL)) e includere il blocco di codice all'interno della stessa. Per favore, puoi spiegare. –

+0

Sì; altrimenti non noterai errori (o vedrai la tua app saltare più tardi). –

risposta

4

Sembra che la perdita di memoria nel codice precedente si verifichi quando viene eseguito il caso "else".

if (sqlite3_open(dbpath, &wazzupco) == SQLITE_OK) 
{ 
    const char *query_stmt; 
    if (exists == 0) 
    { 
     query_stmt = "INSERT INTO media (media_id, title, description, file, views, thumbnail, version, playlist, playlist_id, author, created_at, type, playlist_created, timeout, playlist_order, media_order, playlist_promo_text, playlist_promo_url, playlist_promo_img,video_promo_text, video_promo_url, video_promo_img, dev_id, device_id, downloaded,slide_timeout) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; 
    } 
    else if([[details objectForKey:@"version"] integerValue] > exists) 
    { 
     NSString *querySQL = [NSString stringWithFormat:@"UPDATE %@ SET media_id=?, title=?, description=?, file=?, views=?, thumbnail=?, version=?, playlist=?, playlist_id=?, author=?, created_at=?, type=?, playlist_created=?, timeout=?, playlist_order=?, media_order=?, playlist_promo_text=?, playlist_promo_url=?, playlist_promo_img=?,video_promo_text=?, video_promo_url=?, video_promo_img=?, dev_id=?, device_id=?, downloaded=?, slide_timeout=? WHERE media_id='%@' AND playlist_id='%@' AND type='%@'", TABLE_MEDIA, [details objectForKey:@"media_id"], [details objectForKey:@"playlist_id"], [details objectForKey:@"type"]]; 
     query_stmt = [querySQL UTF8String]; 
    } 
    else 
    { 
     //to make sure we won't update the database entry unless its a newer version 
     return FALSE; 
    } 

Quando il caso altrimenti viene licenziato, la sqlite3_close() non viene raggiunta e la volontà conduce ad una perdita di memoria a sqlite3_open

+0

Grazie mi è davvero mancato ... –

1

spiacenti Iam non hanno familiarità con questi progetti SQL Lite e non ARC Dopo alcuni googling ho trovato questa soluzione per You.Io cosa dovresti considerare la conversione del pr oject to ARC. ARC gestirà la gestione della memoria per te. Quando ARC è attivo, il compilatore inserirà le istruzioni di gestione della memoria appropriate come conservare e rilasciare i messaggi. È preferibile utilizzare ARC poiché il compilatore ha un'idea migliore del ciclo di vita di un oggetto ed è meno incline all'errore umano

per convertire il progetto non ARC in uno attivato da ARC. Questo sito Web può essere d'aiuto Enable ARC

+0

Grazie a Sarath, ma non posso convertire il progetto in ARC a questo punto poiché ci sono molte librerie usate, dove la conversione sarà difficile –

+0

ok :). Spero che qualcuno arriverà con la risposta giusta – SARATH