1

在我的应用程序中,此方法显示内存泄漏如何消除泄漏?

-(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);
    }

}

这种方法也显示泄漏......这种方法有什么问题?

-(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);
}   

}

替代文字 http://www.freeimagehosting.net/uploads/5b8120982c.png

4

4 回答 4

4

您实际上并没有使用在函数顶部初始化的对象:

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

当您稍后用其他对象替换这些对象时:

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

所以那些似乎是泄漏的对象。

于 2009-08-24T09:26:45.553 回答
2

[[NSString alloc] init] 完全没有意义。它将返回与 @"" 完全相同的值,但需要做更多工作。它不太可能泄漏,因为系统几乎肯定会返回一个固定的常量空字符串,在 init 例程中释放 [NSString alloc]。但它是无意义的、无用的和糟糕的代码。

除此之外,您的代码看起来还可以。第二种方法可能被认为是“泄漏”optionsList,仅仅是因为它创建它并且它从未被释放,但它只创建一次,所以它应该没问题。

尝试运行您的程序并进行泄漏检测,然后在调试器中中断并使用

po 0x4b2720(替换为泄露对象的地址)

查看实际泄漏的字符串。

请记住,泄漏可能会产生误报,尤其是在缓存任何内容的情况下。

于 2009-08-24T12:53:41.817 回答
1

[[NSString alloc] init];是一个无用的短语。删除前两条线将消除泄漏。

编辑:也请注意,一旦自动释放池耗尽,您从数据库中提取的两个字符串就会消失,除非它们被保留。

Redit:关于第二种方法;我看不到任何明显的泄漏。NSCFStrings 被创建了很多,并且经常存在。这并不意味着它们实际上是泄漏。据我所知,该方法中的所有内容要么是自动释放的,要么是持久的。

于 2009-08-24T09:28:25.567 回答
1

-1/2

@""相当于[[[NSString alloc] init] autorelease]; [[NSString alloc] init]会泄露。

记住规则:init/retain应该由 平衡autorelease/release

于 2010-04-29T04:50:24.750 回答