内存泄漏返回NSMutableDictionary对象时

时间:2012-01-27 03:55:06

标签: iphone ios4 nsmutabledictionary

我在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];
    }
}

3 个答案:

答案 0 :(得分:1)

您正在泄露sqlite3个对象,因为sqlite3_close成功时您不会在其上调用sqlite3_open

您的方法名为getDataToDisplayTierOne:。通过Cocoa convention,该方法应返回调用者拥有的对象。因此,您应该在返回之前将autorelease发送给aTierOneData。如果您希望调用者拥有返回的对象,则应将该方法命名为newDataToDisplayTierOne:mutableCopyDataToDisplayTierOne:

除非您向我们展示调用getDataToDisplayTierOne:并使用返回字典的代码,否则我们无法帮助您了解应用崩溃的原因。

更新

fetchDataForTierOne中,您正在分配/初始化空NSMutableDictionary,在myTierOneDict中存储指向它的指针,然后通过将myTierOneDict设置为返回来立即泄漏它值getDataToDisplayTierOne:。为什么你认为你需要在myTierOneDict中存储指向空字典的指针?

您发布的代码不会将releaseautorelease发送到getDataToDisplayTierOne:中创建的词典,因此您可能也会泄漏该词典。

您发布的代码不会向release指向的数组发送autoreleasemyTierOneData,因此您可能也会泄漏该代码。

答案 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]; }