如何消除 NSString 相关的内存泄漏?

发布于 2024-08-02 15:20:29 字数 2892 浏览 4 评论 0原文

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

-(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

in my application this method shows memory leak how do i remove leak?

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

}

this method also shows leaks.....what's wrong with this method?

-(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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

墨小墨 2024-08-09 15:20:29

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

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)];

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

You don't actually use the objects you initialise at the top of the function:

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

as you replace those objects with others later on:

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

So those would seem to be the objects that are leaking.

稀香 2024-08-09 15:20:29

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

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

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

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

来查看实际泄漏的字符串。

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

[[NSString alloc] init] is completely pointless. It will return exactly equivalent of @"", except wiht more work. Its unlikely to leak, since the system will almost certainly return you a fixed constant empty string, releasing the [NSString alloc] in the init routine. But it is pointless and useless and bad code.

Other than that, your code looks OK. The second method might be considered to "leak" optionsList, simply because it creates it and it is never released, but its only created once so it should be fine.

Try running your program and doing the leak detection, then breaking in the debugger and using

po 0x4b2720 (replace with the address of the leaked objects)

to see what string is actually leaking.

Remember that Leaks can give false positives, especially if anything is cached.

朮生 2024-08-09 15:20:29

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

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

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

[[NSString alloc] init]; is a useless phrase. Removing the two first lines would get rid of the leak.

EDIT: Note, too, that the two strings you pull from the database will vanish as soon as the autoreleasepool is drained, unless they are retained.

Redit: Concerning the second method; I cannot see any obvious leaks. NSCFStrings are created a lot, and often stick around. That doesn't mean they actually are leaks. From what I can see, everything in that method is either autoreleased or persistent.

秋意浓 2024-08-09 15:20:29

-1/2

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

请记住规则:init/retain 应通过 autorelease/release 进行平衡。

-1/2

@"" is equivalent to [[[NSString alloc] init] autorelease];
[[NSString alloc] init] will leak.

Remember the rule: init/retain should be balanced by autorelease/release.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文