如何消除 NSString 相关的内存泄漏?
在我的应用程序中,此方法显示内存泄漏,我如何消除泄漏?
-(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);
}
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您实际上并没有使用在函数顶部初始化的对象:
因为您稍后将这些对象替换为其他对象:
所以这些对象似乎是泄漏的对象。
You don't actually use the objects you initialise at the top of the function:
as you replace those objects with others later on:
So those would seem to be the objects that are leaking.
[[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.
[[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.
-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 byautorelease/release
.