2009-08-24 14 views
1

in meiner Anwendung zeigt diese Methode Speicherverlust Wie kann ich Leck beseitigen?Wie NSString Related Memory Lecks zu entfernen?

-(void)getOneQuestion:(int)flashcardId categoryID:(int)categoryId 
{ 

    flashCardText = [[NSString alloc] init]; 
    flashCardAnswer=[[NSString alloc] init]; 
    //NSLog(@"%s %d %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__); 

    sqlite3 *MyDatabase; 
    sqlite3_stmt *CompiledStatement=nil; 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *MyDatabasePath = [documentsDirectory stringByAppendingString:@"/flashCardDatabase.sqlite"]; 
    if(sqlite3_open([MyDatabasePath UTF8String],&MyDatabase) == SQLITE_OK) 
    { 
     sqlite3_prepare_v2(MyDatabase, "select flashCardText,flashCardAnswer,flashCardTotalOption from flashcardquestionInfo where flashCardId=? and categoryId=?", -1, &CompiledStatement, NULL); 
     sqlite3_bind_int(CompiledStatement, 1, flashcardId); 
     sqlite3_bind_int(CompiledStatement, 2, categoryId); 
     while(sqlite3_step(CompiledStatement) == SQLITE_ROW) 
     {  
      self.flashCardText = [NSString stringWithUTF8String:(char *)sqlite3_column_text(CompiledStatement,0)]; 
      self.flashCardAnswer= [NSString stringWithUTF8String:(char *)sqlite3_column_text(CompiledStatement,1)]; 
      flashCardTotalOption=[[NSNumber numberWithInt:sqlite3_column_int(CompiledStatement,2)] intValue]; 
     } 
     sqlite3_reset(CompiledStatement); 
     sqlite3_finalize(CompiledStatement); 
     sqlite3_close(MyDatabase); 
    } 

} 

diese Methode zeigt auch Lecks ..... Was ist falsch an dieser Methode?

-(void)getMultipleChoiceAnswer:(int)flashCardId 
{ 
if(optionsList!=nil) 
    [optionsList removeAllObjects]; 
else 
    optionsList = [[NSMutableArray alloc] init]; 

sqlite3 *MyDatabase; 
sqlite3_stmt *CompiledStatement=nil; 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *MyDatabasePath = [documentsDirectory stringByAppendingString:@"/flashCardDatabase.sqlite"]; 
if(sqlite3_open([MyDatabasePath UTF8String],&MyDatabase) == SQLITE_OK) 
{ 
    sqlite3_prepare_v2(MyDatabase,"select OptionText from flashCardMultipleAnswer where flashCardId=?", -1, &CompiledStatement, NULL); 
    sqlite3_bind_int(CompiledStatement, 1, flashCardId); 
    while(sqlite3_step(CompiledStatement) == SQLITE_ROW) 
    {  
     [optionsList addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(CompiledStatement,0)]]; 
    } 
    sqlite3_reset(CompiledStatement); 
    sqlite3_finalize(CompiledStatement); 
    sqlite3_close(MyDatabase); 
} 

}

alt text http://www.freeimagehosting.net/uploads/5b8120982c.png

Antwort

4

Sie eigentlich nicht die Objekte verwenden Sie an der Spitze der Funktion initialisieren:

flashCardText = [[NSString alloc] init]; 
flashCardAnswer=[[NSString alloc] init]; 

, wie Sie diese Objekte durch andere ersetzen später :

self.flashCardText = [NSString stringWithUTF8String:(char *)sqlite3_column_text(CompiledStatement,0)]; 
self.flashCardAnswer= [NSString stringWithUTF8String:(char *)sqlite3_column_text(CompiledStatement,1)]; 

So scheinen das die Objekte zu sein, die undicht sind.

+0

Ich habe diese beiden Zeilen entfernt, aber immer noch zeigt leak..i ein Bild –

+0

von Instrumenten am Zusatz i flashcardtext bin mit Text auf einem Etikett zeigen ... aber ich bin mit flashcardanswer in derselben Klasse 3-4 mal...aber zeigen Text in einer anderen Klasse ... wenn ich selbst aus Flashcardanswer App entfernen. stürzt ab –

+0

Sie würden nicht lecken, da die Eigenschaft (vermutlich) die (sinnlosen) Anfangswerte von flashCardText und flashCardAnswer freigeben würde. –

1

[[NSString alloc] init]; ist eine sinnlose Phrase. Das Entfernen der zwei ersten Linien würde das Leck beseitigen.

EDIT: Beachten Sie auch, dass die zwei Zeichenfolgen, die Sie aus der Datenbank ziehen, verschwinden, sobald der Autorespulepool leer ist, sofern sie nicht beibehalten werden.

Redit: Bezüglich der zweiten Methode; Ich kann keine offensichtlichen Lecks sehen. NSCFStrings werden oft erstellt und bleiben oft dabei. Das bedeutet nicht, dass sie tatsächlich Lecks sind. Soweit ich sehen kann, ist alles in dieser Methode entweder autoreleased oder persistent.

+0

Guter Punkt über die Autorelease, hatte ich nicht abgeholt auf diesem. Geht zu zeigen, dass es möglich ist, sich zu sehr auf die Frage zu konzentrieren, die gefragt wurde :-) –

+0

also sollte ich eine Eigenschaft in Header-Datei wie diese erstellen @property (nonatomic, behalten) NSString * flashCardText; oder wie folgt @property (nicht atomare, kopieren) NSString * flashCardText; –

+0

'@property (nichtatomare, Kopie)' wird allgemein als am besten für Saiten, sofern ich mich erinnere. –

2

[[NSString Alloc] Init] ist völlig sinnlos. Es wird genau das Äquivalent von @ "" zurückgegeben, außer mit mehr Arbeit. Es ist unwahrscheinlich, dass es undicht wird, da das System fast sicher eine feste konstante leere Zeichenfolge zurückgibt, die die [NSString-Zuweisung] in der Init-Routine freigibt. Aber es ist sinnlos und nutzlos und schlechter Code.

Ansonsten sieht Ihr Code OK aus. Die zweite Methode könnte so aussehen, dass sie optionsList "leckt", weil sie einfach erstellt wird und niemals veröffentlicht wird, aber nur einmal erstellt wird, damit sie in Ordnung ist.

Versuchen Sie Ihr Programm läuft und die Leckerkennung zu tun, dann im Debugger zu brechen und mit

po 0x4b2720 (ersetzen mit der Adresse der durchgesickerten Objekte)

zu sehen, welche Zeichenfolge tatsächlich undicht.

Denken Sie daran, dass Leaks falsche Ergebnisse liefern können, insbesondere wenn etwas zwischengespeichert wird.

+0

+1 für die Debugging-Methoden. – Abizern

+0

das funktioniert nicht po 0x4b2720 (ersetzen durch die Adresse der durchgesickerten Objekte) gdb druckt nichts ... –

1

-1/2

@"" entspricht [[[NSString alloc] init] autorelease]; [[NSString alloc] init] undicht wird.

Erinnern Sie sich an die Regel: init/retain sollte durch autorelease/release ausgeglichen werden.