views:

479

answers:

1

my UITableView have serious memory leak problem only when the NSString is NOT encoding with NSASCIIStringEncoding.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"cell";
    UILabel *textLabel1;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        textLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(105, 6, 192, 22)];

        textLabel1.tag = 1;
        textLabel1.textColor = [UIColor whiteColor];
        textLabel1.backgroundColor = [UIColor blackColor];
        textLabel1.numberOfLines = 1;
        textLabel1.adjustsFontSizeToFitWidth = NO;
        [textLabel1 setFont:[UIFont boldSystemFontOfSize:19]];
        [cell.contentView addSubview:textLabel1];
        [textLabel1 release];

    } else {
        textLabel1 = (UILabel *)[cell.contentView viewWithTag:1];
    }

    NSDictionary *tmpDict = [listOfInfo objectForKey:[NSString stringWithFormat:@"%@",indexPath.row]];

    textLabel1.text = [tmpDict objectForKey:@"name"];

    return cell;
}

-(void) readDatabase {
    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [documentPaths objectAtIndex:0];
    databasePath = [documentsDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",myDB]];
    sqlite3 *database;

    if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {

        const char sqlStatement = [[NSString stringWithFormat:@"select id,name from %@ order by orderid",myTable] UTF8String];
        sqlite3_stmt *compiledStatement;
        if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
            while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
                NSString *tmpid = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];


                NSString *tmpname = [NSString stringWithCString:(const char *)sqlite3_column_text(compiledStatement, 1) encoding:NSUTF8StringEncoding];


                [listOfInfo setObject:[[NSMutableDictionary alloc] init] forKey:tmpid];
                [[listOfInfo objectForKey:tmpid] setObject:[NSString stringWithFormat:@"%@", tmpname] forKey:@"name"];


            }
        }
        sqlite3_finalize(compiledStatement);

        debugNSLog(@"sqlite closing");

    }
    sqlite3_close(database);

}

when i change the line

NSString *tmpname = [NSString stringWithCString:(const char *)sqlite3_column_text(compiledStatement, 1) encoding:NSUTF8StringEncoding];

to

NSString *tmpname = [NSString stringWithCString:(const char *)sqlite3_column_text(compiledStatement, 1) encoding:NSASCIIStringEncoding];

the memory leak is gone

i tried NSString stringWithUTF8String and it still leak. i've also tried:

NSData *dtmpname = [NSData dataWithBytes:sqlite3_column_blob(compiledStatement, 1) length:sqlite3_column_bytes(compiledStatement, 1)];
NSString *tmpname = [[[NSString alloc] initWithData:dtmpname encoding:NSUTF8StringEncoding] autorelease];

and the problem remains, the leak occur when u start scrolling the tableview.

i've actually tried other encoding and it seems that only NSASCIIStringEncoding works(no memory leak)

if i did not scroll the tableview before i close the view, it's no leak at all. actually listOfInfo itself didn't leak, since the leak never occur when i remove the line

textLabel1.text = [tmpDict objectForKey:@"name"];

any idea/workaround how to get rid of this problem?

note: i do have

for (id theKey in listOfInfo) {
   [[listOfInfo objectForKey:theKey]  release];
}
[listOfInfo release];

on dealloc already

+3  A: 

The leak in your program is actually here:

[listOfInfo setObject:[[NSMutableDictionary alloc] init] forKey:tmpid];

You are allocating the dictionary and never releasing it, so it leaks. You should write:

[listOfInfo setObject:[[[NSMutableDictionary alloc] init] autorelease] forKey:tmpid];

or

[listOfInfo setObject:[NSMutableDictionary dictionary] forKey:tmpid];

Since this dictionary contains your strings, the string leaks along with the dictionary. Changing to NSASCIIStringEncoding doesn't fix this leak, it probably just disguises it (since the string will need to be subsequently converted and Leaks might not track it to its new location) or the conversion might fail entirely (if the string can't be converted to ASCII).

Matt Gallagher
i do have [listOfInfo release] on dealloc. it can't be autorelease because i need this variable elsewhere.actually the leak i have is not related to listOfInfo. if i didn't scroll the tableview there are no leak at all.
vince
actually if the view dealloc before any scrolling action. it will have no leak at all. "leaks" shows no problem, scrolling few hundred records with "object allocations" it will have few MB memory leak after dealloc of the view and crash easy in a few times.with ascii encoding it's also fine.
vince
Releasing listOfInfo will not fix the leak that I listed. listOfInfo and the dictionary you add to it with setObject:forKey: are two different dictionaries.
Matt Gallagher
i have for (id theKey in listOfInfo) { [[listOfInfo objectForKey:theKey] release];}[listOfInfo release];actually it's nothing related to listOfInfo leak itself and it's being handled. the leak is too noticeable that changed to ASCII encoding will fix the problem right away.also note that no leak at all if you didn't scroll the tableview before you close the view.
vince