如何解决 SKDatabase 函数中的内存泄漏?
Posted
技术标签:
【中文标题】如何解决 SKDatabase 函数中的内存泄漏?【英文标题】:How to solve Memory leak in SKDatabase function? 【发布时间】:2013-05-24 13:02:25 【问题描述】:仪器在以下代码中显示内存泄漏。我确保在任何地方都保持保留计数。我还添加了自动释放池,仍然存在内存泄漏。如何解决?
代码块:
- (NSArray *)lookupAllForSQL:(NSString *)sql
sqlite3_stmt *statement;
id result = nil;
NSMutableArray *thisArray = [NSMutableArray arrayWithCapacity:4];
statement = [self prepare:sql];
if (statement)
while (sqlite3_step(statement) == SQLITE_ROW)
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableDictionary *thisDict = [NSMutableDictionary dictionaryWithCapacity:4];
for (int i = 0 ; i < sqlite3_column_count(statement) ; i++)
NSAutoreleasePool *poolInside = [[NSAutoreleasePool alloc] init];
if(sqlite3_column_type(statement,i) == SQLITE_NULL)
continue;
if (sqlite3_column_decltype(statement,i) != NULL &&
strcasecmp(sqlite3_column_decltype(statement,i),"Boolean") == 0)
result = [NSNumber numberWithBool:(BOOL)sqlite3_column_int(statement,i)];
else if (sqlite3_column_type(statement,i) == SQLITE_INTEGER)
result = [NSNumber numberWithInt:(int)sqlite3_column_int(statement,i)];
else if (sqlite3_column_type(statement,i) == SQLITE_FLOAT)
result = [NSNumber numberWithFloat:(float)sqlite3_column_double(statement,i)];
else
if((char *)sqlite3_column_text(statement,i) != NULL)
//result = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,i)];
[thisDict setObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,i)]
forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement,i)]];
//[result release];
result = nil;
if (result)
[thisDict setObject:result forKey:[NSString stringWithUTF8String:sqlite3_column_name(statement,i)]];
[poolInside drain];
[thisArray addObject:[NSDictionary dictionaryWithDictionary:thisDict]];
[pool drain];
sqlite3_finalize(statement);
return thisArray;
仪器截图:
【问题讨论】:
偶尔 SQLite 会出错并返回一个字符串,你必须自己给free()
。看看是不是这个问题。
@CodaFi 看来你是对的。需要正确处理返回变量而不是此函数中的变量。谢谢
你可能想在那个人的 repo 上提出一个问题。
嗨,我再次编辑了我的答案。我真的认为“继续”是(或现在)问题。
@LuisEspinoza 我从此代码块中删除了自动释放池代码。我刚刚发布了正确保存 skdatabase 输出的所有变量。现在仪器在这个函数中没有显示任何泄漏。
【参考方案1】:
我得到了解决方案。这个函数返回一个 NSArray,我没有正确释放它。因此,所有这些变量都导致了内存泄漏,而不是这个函数。
This video 帮助我理解了这一点。
【讨论】:
【参考方案2】:我认为continue
语句可能有问题。由于continue
语句导致控制转到最近循环的下一个交互,如果条件(sqlite3_column_type(statement,i) == SQLITE_NULL)
是true
,则控制将传递到下一个迭代并且'poolInside' 池不会被耗尽。所以我会使用:
if(sqlite3_column_type(statement,i) == SQLITE_NULL)
[poolInside drain];
continue;
但是,这可能是您在尝试解决泄漏时添加的错误,因此来自@CodaFi 的评论仍然有效。
为了完整起见
如果你们都看看poolInside
泄漏的后果,你可以看到这一行:
[thisArray addObject:[NSDictionary dictionaryWithDictionary:thisDict]];
每个poolInside
泄漏都会泄漏一个NSDictionary
。因此,这意味着返回的数组将包含泄漏的对象。另外,我怀疑泄漏嵌套的 NSAutoreleasePool 可能会导致在 for 循环中创建的对象也被泄漏。我认为您发布的“仪器屏幕截图”显示了这种行为。
【讨论】:
以上是关于如何解决 SKDatabase 函数中的内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章