-2

I have memory leaks in the aTierOneData and when i tried [aTierOneData autorelease] , my app crashed.so how i can fix this memory leak.

Plese let me know

//===============================================================
  - ( 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];
    }
}
user198725878
  • 6,266
  • 18
  • 77
  • 135
  • In the method that calls this method, what does it do with the returned dictionary? Does it assign it to a retained iVar? If so, then you should be able to do: return [aTierOneData autorelease]; – Rayfleck Jan 27 '12 at 04:06
  • What you are doing exactly in the method from where you are calling ? – Ajay Sharma Jan 27 '12 at 04:28

3 Answers3

1

You are leaking the sqlite3 object, because you don't call sqlite3_close on it when sqlite3_open succeeds.

Your method is named getDataToDisplayTierOne:. By Cocoa convention, that method should return an object that the caller does not own. So you should be sending autorelease to aTierOneData before returning it. If you want the caller to own the returned object, you should name the method something like newDataToDisplayTierOne: or mutableCopyDataToDisplayTierOne:.

We can't help you understand why your app crashes unless you show us the code that calls getDataToDisplayTierOne: and uses the returned dictionary.

Update

In fetchDataForTierOne, you are allocating/initing an empty NSMutableDictionary, storing a pointer to it in myTierOneDict, and then immediately leaking it by setting myTierOneDict to the return value of getDataToDisplayTierOne:. Why did you think you needed to store a pointer to an an empty dictionary in myTierOneDict?

The code you posted doesn't send release or autorelease to the dictionary created in getDataToDisplayTierOne:, so you might be leaking that dictionary also.

The code you posted doesn't send release or autorelease to the array that myTierOneData points to, so you might be leaking that also.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
0

do

return [aTierOneData autorelease];

as cocoa naming convention, You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy”. Your function name doesn't imply that this function create an object that is owned by you, so autorelease the return value. If you need to hold the data that is returned, take ownership of it by sending retain in your class.

X Slash
  • 4,133
  • 4
  • 27
  • 35
0

In the function fetchDataForTierOne, first line myTierOneDict = [[NSMutableDictionary alloc]init]; is creating memory leak. You are creating a dictionary and assigned a different dictionary returned by getDataToDisplayTierOne function.

So, the dictionary created in the first line of function fetchDataForTierOne will become unreferenced and will create a leak. No need to write first line.

Second, return the dictionary with autorelease and retain it in fetchDataForTierOne function. After completing the usage release it.

Updated Code:

//===============================================================

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

}

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

Apurv
  • 17,116
  • 8
  • 51
  • 67