我在aTierOneData中有内存泄漏,当我尝试[aTierOneData autorelease]时,我的应用程序崩溃了。我怎么能修复这个内存泄漏。
请告诉我
//===============================================================
- ( NSMutableDictionary * ) getDataToDisplayTierOne:(NSString*)dbPath{
//================================================================
NSMutableDictionary *aTierOneData = [[NSMutableDictionary alloc]init];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
const char *sql_query_stmt = "select * from main_categories";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql_query_stmt, -1, &selectstmt, NULL) == SQLITE_OK)
{
while(sqlite3_step(selectstmt) == SQLITE_ROW)
{ NSString *aValue = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selectstmt, 1)];
NSString *aId = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selectstmt, 0)];
[aTierOneData setObject:aId forKey:aValue];
[aValue release];
[aId release];
}
}
}
else{//Even though the open call failed, close the database connection to
sqlite3_close(database);
}
return aTierOneData;
}
-(void)fetchDataForTierOne{
//===========================
myTierOneDict = [[NSMutableDictionary alloc]init];
myTierOneDict = [myDBOperations getDataToDisplayTierOne:[appDelegate getDBPath]];
NSArray *myTierOneDictKeys = [myTierOneDict allKeys];
myTierOneData = [[NSMutableArray alloc] initWithArray:(NSArray*)myTierOneDictKeys];
if ([myTierOneData count] > 0 ){
[self constructTierOnePicker];
}
}
答案 0 :(得分:1)
您正在泄露sqlite3
个对象,因为sqlite3_close
成功时您不会在其上调用sqlite3_open
。
您的方法名为getDataToDisplayTierOne:
。通过Cocoa convention,该方法应返回调用者不拥有的对象。因此,您应该在返回之前将autorelease
发送给aTierOneData
。如果您希望调用者拥有返回的对象,则应将该方法命名为newDataToDisplayTierOne:
或mutableCopyDataToDisplayTierOne:
。
除非您向我们展示调用getDataToDisplayTierOne:
并使用返回字典的代码,否则我们无法帮助您了解应用崩溃的原因。
在fetchDataForTierOne
中,您正在分配/初始化空NSMutableDictionary
,在myTierOneDict
中存储指向它的指针,然后通过将myTierOneDict
设置为返回来立即泄漏它值getDataToDisplayTierOne:
。为什么你认为你需要在myTierOneDict
中存储指向空字典的指针?
您发布的代码不会将release
或autorelease
发送到getDataToDisplayTierOne:
中创建的词典,因此您可能也会泄漏该词典。
您发布的代码不会向release
指向的数组发送autorelease
或myTierOneData
,因此您可能也会泄漏该代码。
答案 1 :(得分:0)
DO
return [aTierOneData autorelease];
作为可可命名约定,You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”。您的函数名称并不意味着此函数创建了您拥有的对象,因此autorelease
返回值。如果您需要保留所返回的数据,请在您的课程中发送retain
来获取所有权。
答案 2 :(得分:0)
在函数fetchDataForTierOne中,第一行myTierOneDict = [[NSMutableDictionary alloc] init];正在创建内存泄漏。您正在创建一个字典并分配了一个由getDataToDisplayTierOne函数返回的不同字典。
因此,在函数fetchDataForTierOne的第一行中创建的字典将变为未引用并将产生泄漏。无需写第一行。
其次,使用autorelease返回字典并将其保留在fetchDataForTierOne函数中。完成使用后,将其发布。
更新代码:
// ============================================= ==================
- (NSMutableDictionary *)getDataToDisplayTierOne:(NSString *)dbPath { // ================================================ ================
NSMutableDictionary *aTierOneData = [[NSMutableDictionary alloc]init];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
{
const char *sql_query_stmt = "select * from main_categories";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql_query_stmt, -1, &selectstmt, NULL) == SQLITE_OK)
{
while(sqlite3_step(selectstmt) == SQLITE_ROW)
{ NSString *aValue = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selectstmt, 1)];
NSString *aId = [[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(selectstmt, 0)];
[aTierOneData setObject:aId forKey:aValue];
[aValue release];
[aId release];
}
}
}
else{//Even though the open call failed, close the database connection to
sqlite3_close(database);
}
return [aTierOneData autorelease];
}
- (无效)fetchDataForTierOne {
// ===========================
myTierOneDict = [[myDBOperations getDataToDisplayTierOne:[appDelegate getDBPath]]retain];
NSArray *myTierOneDictKeys = [myTierOneDict allKeys];
myTierOneData = [[NSMutableArray alloc] initWithArray:(NSArray*)myTierOneDictKeys];
if ([myTierOneData count] > 0 ){
[self constructTierOnePicker];
}
[myTierOneDict release]; }