iPhone - database reading method and memory leaks
in my application, a RSS r开发者_如何转开发eader, I get memory leaks that I can't fix because I can't understand from where they come from. Here is the code pointed out by Instruments.
-(void) readArticlesFromDatabase {
[self setDatabaseInfo];
sqlite3 *database;
articles = [[NSMutableArray alloc] init];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select * from articles";
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aDate = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aUrl = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSString *aCategory = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 4)];
NSString *aAuthor = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 5)];
NSString *aSummary = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 6)];
NSMutableString *aContent = [NSMutableString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 7)];
NSString *aNbrComments = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 8)];
NSString *aCommentsLink = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 9)];
NSString *aPermalink = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 11)];
[aContent replaceCharactersInRange: [aContent rangeOfString: @"http://www.mywebsite.com/img/action-on.gif"] withString: @"hellocoton-action-on.gif"];
[aContent replaceCharactersInRange: [aContent rangeOfString: @"hhttp://www.mywebsite.com/img/action-on-h.gif"] withString: @"hellocoton-action-on-h.gif"];
[aContent replaceCharactersInRange: [aContent rangeOfString: @"hthttp://www.mywebsite.com/img/hellocoton.gif"] withString: @"hellocoton-hellocoton.gif"];
NSString *imageURLBrut = [self parseArticleForImages:aContent];
NSString *imageURLCache = [imageURLBrut stringByReplacingOccurrencesOfString:@":" withString:@"_"];
imageURLCache = [imageURLCache stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
imageURLCache = [imageURLCache stringByReplacingOccurrencesOfString:@" " withString:@"_"];
NSString *uniquePath = [tmp stringByAppendingPathComponent: imageURLCache];
if([[NSFileManager defaultManager] fileExistsAtPath: uniquePath]) {
imageURLCache = [@"../tmp/" stringByAppendingString: imageURLCache];
[aContent replaceCharactersInRange: [aContent rangeOfString: imageURLBrut ] withString: imageURLCache];
}
Article *article = [[Article alloc] initWithName:aName date:aDate url:aUrl category:aCategory author:aAuthor summary:aSummary content:aContent commentsNbr:aNbrComments commentsLink:aCommentsLink commentsRSS:@"" enclosure:aPermalink enclosure2:@"" enclosure3:@""];
[articles addObject:article];
article = nil;
[article release];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
`
I have a lot of "Article" leaked and NSString matching with these using :
[NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, X)];
I tried a lot of different code I always have these leaks. Anyone has got an idea to help me?
You are leaking articles because:
article = nil;
[article release];
Why are you attempting to release nil?
Just remove the line setting article to nil, it is not needed. Given the above sample, there are probably a lot more problems in that code.
I just spent the last few days tracking this down and below resolved the issue for me.
Adding a dealloc method to your articles NSObject and release all strings. Then in your readArticlesFromDatabase method first release articles and then do your init.
I finally found a part of the solution by myself.
My mistake was to initialize the "articles" array INTO my function. Indeed, each time I called my function, I lost the previous data in this array. Now I initialize the "articles" array during launching and I simply remove its content in my function as that :
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// My Code
articles = [[NSMutableArray alloc] init];
// My Code
}
Then
-(void) readArticlesFromDatabase {
[self setDatabaseInfo];
sqlite3 *database;
[articles removeAllObjects];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select * from articles";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *aDate = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 2)];
NSString *aUrl = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 3)];
NSString *aCategory = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 4)];
NSString *aAuthor = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 5)];
NSString *aSummary = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 6)];
NSMutableString *aContent = [NSMutableString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 7)];
NSString *aNbrComments = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 8)];
NSString *aCommentsLink = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 9)];
NSString *aPermalink = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 11)];
[aContent stringByReplacingOccurrencesOfString: @"http://www.mywebsite.com/img/action-on.gif" withString: @"hellocoton-action-on.gif"];
[aContent stringByReplacingOccurrencesOfString: @"http://www.mywebsite.com/img/action-on-h.gif" withString: @"hellocoton-action-on-h.gif"];
[aContent stringByReplacingOccurrencesOfString: @"http://www.mywebsite.com/img/hellocoton.gif" withString: @"hellocoton-hellocoton.gif"];
NSString *imageURLBrut = [self parseArticleForImages:aContent];
NSString *imageURLCache = [imageURLBrut stringByReplacingOccurrencesOfString:@":" withString:@"_"];
[imageURLCache stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
[imageURLCache stringByReplacingOccurrencesOfString:@" " withString:@"_"];
NSString *uniquePath = [tmp stringByAppendingPathComponent: imageURLCache];
if([[NSFileManager defaultManager] fileExistsAtPath: uniquePath]) {
imageURLCache = [@"../tmp/" stringByAppendingString: imageURLCache];
[aContent replaceCharactersInRange: [aContent rangeOfString: imageURLBrut ] withString: imageURLCache];
}
Article *article = [[Article alloc] initWithName:aName date:aDate url:aUrl category:aCategory author:aAuthor summary:aSummary content:aContent commentsNbr:aNbrComments commentsLink:aCommentsLink commentsRSS:@"" enclosure:aPermalink enclosure2:@"" enclosure3:@""];
[articles addObject:article];
[article release];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
Now I have to focus on the "Article" leaks caused by [articles removeAllObjects]. If I don't remove all objects I don't have any leaks but if I do, I have got leaks. Any idea? How could I empty my array without leaking these Article Objects?
精彩评论