views:

97

answers:

2

Dear Developers, I am getting a potential leak in these methods..can anyone please help me..Leak in method 1 is in line 5..I am referencing this method from another class as [sync loginHandler] where sync is an object of the class which has the method loginHandler..

-(void) loginHandler
{
1   SCRMsugarsoap* service = [[SCRMsugarsoap alloc] initWithUrl:serverURL];
2   service.logging = YES;
3   service.username = userName;
4   service.password = password;
5   [service login:self action:@selector(sessionIdHandler:) user_auth: [[[SCRMuser_auth alloc] initWithUsername:userName andPassword:password]autorelease] application_name: @""];
6   [service release];
}

And another method where I have problems with leaks is

-(NSMutableArray *)searchContacts:(NSString *)tableName bySearchString:(NSString *)searchString
{

1   NSString *sid=@"";
2   NSString *firstname=@"";
3   NSString *lastname=@"";
4   NSString *qsql;
    //NSArray *contactArray=[[NSArray alloc]init];
5   searchArray=[[NSMutableArray alloc]init];

6   qsql=[NSString stringWithFormat:@"SELECT DISTINCT sugar_id,first_name,last_name FROM CONTACTS where last_name LIKE '%%%@%%' OR first_name LIKE '%%%@%%' GROUP BY sugar_id ORDER BY last_name",searchString,searchString];
7   sqlite3_stmt *statement;
8   if (sqlite3_prepare_v2( db, [qsql UTF8String], -1, &statement, nil) == SQLITE_OK) {
9       while (sqlite3_step(statement) == SQLITE_ROW) 
10      {
                //TODO: alloc Contact object
11          Contact *contacts=[[Contact alloc]init];

12          sid = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
13          firstname = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 1)];
14          lastname = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 2)];
15

16          if ([firstname isEqualToString:@"(null)"]) {
                lastname=[lastname stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[lastname substringToIndex:1] uppercaseString]];
17              contacts.lastName=lastname;
18              contacts.sugarId=sid;
19              contacts.firstName=@"";


                }
20          else {

21              firstname=[firstname stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[firstname substringToIndex:1] uppercaseString]];
22              lastname=[lastname stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[lastname substringToIndex:1] uppercaseString]];
23              contacts.firstName=firstname;
24              contacts.lastName=lastname;
25              contacts.sugarId=sid;


            }
26          [searchArray addObject:contacts];
            //searchArray=[NSMutableArray arrayWithObjects:contacts];           
            //TODO:  Release contacts variable
27          [contacts release];
28          [sid release]; //not sure about releasing these objects..just gave a try
29          [firstname release];
30          [lastname release];
31          firstname = nil;
32          lastname = nil;
33          sid=nil;


        }       
34      sqlite3_reset(statement);


    }

35  sqlite3_finalize(statement);
36  return searchArray; 
}

I am releasing searchArray in dealloc method. The leaks are between lines 5,11-14,16,21,22.These lines vary whenever I try to fiddle with the code..please help me guys..waiting for your suggestions..

I tried using instruments and these are the areas figured out using it..Can I also use build and analyze in xcode..I used that and made some changes to the code..

EDIT (Added methods that code 1 refers)

- (id) initWithUsername: (NSString*) username andPassword: (NSString*) pass 
    {
        if(self = [super init])
        {
            Soap *converter = [[Soap alloc] init];
            SCRMsugarsoap *service = [[SCRMsugarsoap alloc] init];

            [service get_server_version:self action:@selector(get_server_versionHandler:)];

            self.user_name = username;
            self.password = [converter tomd5:pass];

            [converter release];
            [service release];
        }
        return self;
    }

-(NSString*)tomd5:(NSString*)value{
    const char *cStr = [value UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, strlen(cStr), result);
    return [NSString stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
            result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]
    ];
}
A: 

Well, from in the first method you allocate an SCRMuser_auth that you don't hold a pointer to so that object will definitely leak.

I am not quite sure in your second section of code but I will keep looking over it.

IphoneDev
Thanks for the reply..so you don't want to autorelease the object in line 5..can you explain in detail please..
racharambola
Autoreleasing is acceptable, the SCRMuser_auth is not leaking.
Jerry Jones
Jerry..thanks for the reply..I edited the methods for the code1..i.e. I include SCRM_auth method initWithUserNameandPassword and tomd5 method..please help me
racharambola
+1  A: 

If searchArray is an instance variable, and you call searchContacts more than once, you will leak the previous value stored in searchArray.

You need to do something like...

[searchArray release];
searchArray=[[NSMutableArray alloc] init];

Sending messages to nil objects has no effect, so if searchArray hasn't been set, calling release will do nothing. On subsequent calls, you will release search array before letting go of the pointer to it.

Edit: Also, you are over releasing sid, firstName and lastName. Objects returned by class convenience methods like that are almost always returned autoreleased. Take a look at the Memory Management Guide

Jerry Jones
I commented out the release statements for sid,firstname and lastname..it was purely my guess.should I release the array in dealloc method or releasing the array in searchcontacts method is enough??
racharambola
You would still need to release the array in the dealloc method.When you call searchContacts, you are making searchArray point to a newly created mutable array. If searchContacts were never to be called again, this array would be leaked, which is why you still need to release in your dealloc method.
Jerry Jones
thanks jerry..that almost solved my problem..but I tried to refer memory management guide and couldn't figure out the problem with first method..also when I tried to get 200 contacts on my iphone it is retrieving successfully but when I tried to get 4000 contacts the app gets crashed..is it because of the leak..
racharambola
There is nothing wrong with the first method.Take a look at a tutorial for the leaks tool in instruments.http://www.mobileorchard.com/find-iphone-memory-leaks-a-leaks-tool-tutorial/
Jerry Jones