views:

124

answers:

3

Hello all, i have the following code which shows memory leak for object favorite near the statement with stringWithUTF8String.

i have declared favorites in the property

-(NSMutableArray *) readFavoritesFromDatabase 
{
 // Check if database is present
 [self setDatabaseNameAndPath];
 [self checkAndCreateDatabase];

 // Setup the database object
 sqlite3 *database;

 //Initialize favorites array
 if (favorites == nil) 
 {
  [favorites release];
  favorites = [[NSMutableArray alloc] init];
 }
 else 
 {
  favorites = nil;
  [favorites removeAllObjects];
 }


 // Open the database from the users file system
 if(sqlite3_open([self.dataBasePath UTF8String], &database) == SQLITE_OK) 
 {
  // Setup the SQL Statement and compile it for faster access
  const char *sqlStatement = "select * from Favorites";
  sqlite3_stmt *compiledStatement;

  if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) 
  {

   // Loop through the results and add them to the favorites array
   while(sqlite3_step(compiledStatement) == SQLITE_ROW) 
   {
    // Create Favorite object and add it to the Favorite array
    Favorite *favorite = [[[Favorite alloc] init] autorelease];

    favorite.cameraID = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(compiledStatement, 0)];
    favorite.cameraName = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(compiledStatement, 1)];
    favorite.cameraLink = [NSString stringWithUTF8String:(const char*)sqlite3_column_text(compiledStatement, 2)];

    [self.favorites addObject:favorite];
    //[favorite.cameraID release];
//    [favorite.cameraName release];
//    [favorite.cameraLink release];
   }

   // If favorite cameras exists in database, then sort the Favorites array 
   if([self.favorites count]>0)
   {

    NSSortDescriptor *favoritesNameSorter = [[NSSortDescriptor alloc] initWithKey:@"cameraName" ascending:YES];
    [self.favorites sortUsingDescriptors:[NSArray arrayWithObject:favoritesNameSorter]];
    [favoritesNameSorter release];
   }
  }

  // Release the compiled statement from memory
  sqlite3_finalize(compiledStatement);
 }

 // Close the database
 if(database !=nil)
 {
  sqlite3_close(database);
  return self.favorites;
 }
 else 
 {
  return nil;
 }
}

Please let me know how to solve this memory leak problem Thanks in advance.

A: 

I don't see any leak in your stringWithUTF8String, that code works well. However, look at the whole method, I found something can create memory problems like leaking or crashing. If you already declared a property for favorites, then you should use self.favorites here

 //Initialize favorites array
 if (favorites == nil) 
 {
  [favorites release];
  favorites = [[NSMutableArray alloc] init];
 }
 else 
 {
  favorites = nil;
  [favorites removeAllObjects];
 }

becomes:

 //Initialize favorites array
 if (self.favorites == nil) 
 {
  self.favorites = [[NSMutableArray alloc] init];
 }
 else 
 {
  self.favorites = nil;
 }

It will help you a lot of things in memory managements, like in your else condition, you set the variable to nil but not release it, and in the first condition, you release a nil object?

vodkhang
I think my first answer was not clear enough and not really directly answer the question. Hope that the editted version clarify and help something to the questioner
vodkhang
If the `favorites` property is defined as `(retain)`, you should NOT use this.
Douwe Maan
+1 to not using this if it's retain.
jer
humm? Why not, I think you should use it if the property is (retain), because it will do release and set to new object and then retain for you, right?
vodkhang
i have used assign for favorites and not retain
+1  A: 

Use this safe method:

Favorite *tempFavorite = [[Favorite alloc] init];
self.favorite = tempFavorite;
[tempFavorite release];

Normaly, in your Favorite dealloc function, you should remove all objects and clean what necessary before calling the super dealloc function.

Using this way, you don't need to worry about if favorite is nil or not since objective-c allows calling methods for nil objects

Regards

Meir Assayag

Meir Assayag
favorite here is a local variable. So I don't see a reason to do this. Please elaborate.
+1  A: 

Not sure about the stringWithUTF8String leak, but this is a problem:

favorites = nil;
[favorites removeAllObjects];

You leak what was in favorites and then tell a nil object to remove all objects -- it's nil, by definition it has none. Then later on you try to add objects to it; that won't work either.

Stephen Darlington
i had earlier kept only [favorites removeAllObjects] only but that didn't either remove the memory leaks. This code is working fine
What happens to the old contents of `favorites` after you assign `nil` to it?
Stephen Darlington