Newbie leaks that I don't quite understand
After fixing other leaks that Instruments was indicating, I find myself in need for help to find my leaches in the following code:
-(void) readHistoryFromDatabase { sqlite3 *database;
NSMutableArray *days = [[NSMutableArray alloc] init];
NSInteger currentMonth;
int noMonths = 0;
int historyCount = 0;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"yyyy-MM-dd"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"database.sqlite"];
if(sqlite3_open([filePath UTF8String], &database) == SQLITE_OK) {
const char *sqlStatement = "select data, rata, var, strftime('%m', data) month from rates where id=?";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_int(compiledStatement, 1, id);
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSDate *data = [dateFormat dateFromString:[NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 0)]];
NSString *rata = [NSString stringWithUT开发者_如何学CF8String:(char *) sqlite3_column_text(compiledStatement, 1)];
NSString *var = [NSString stringWithUTF8String:(char *) sqlite3_column_text(compiledStatement, 2)];
NSInteger month = sqlite3_column_int(compiledStatement, 3);
if ((currentMonth != month) && (historyCount > 0)) {
[self.rate setValue:[days copy] forKey:[NSString stringWithFormat:@"%d", noMonths]];
noMonths++;
[days removeAllObjects];
currentMonth = month;
} else if (historyCount == 0) {
currentMonth = month;
}
CHis *new = [[CHis alloc] init];
new.rata = rata;
new.var = variatie;
new.month = month;
new.data = data;
historyCount++;
[days addObject:new];
[new release];
}
if ([days count] > 0) {
[self.rate setValue:[days copy] forKey:[NSString stringWithFormat:@"%d", noMonths]];
}
}
sqlite3_finalize(compiledStatement);
}
[dateFormat release];
[days release];
sqlite3_close(database);
}
self.rate is defined this way:
@property (nonatomic, retain) NSMutableDictionary *rate;
and in viewDidLoad:
self.rate = [[NSMutableDictionary alloc] init];
Basically this part of code reads from a database some rates. Based on the month it will put in a NSDictionary a pair of month and an Array with the rates.
I don't understand where is the leak. I know that perhaps it is something very easy but I am searching for 2 days now for a solution .....
[[NSMutableDictionary alloc] init]
returns an object with retain count 1. Then you assign it to self.rate
which increases the retain count (will then be 2). If you assign something else to self.rate
, the previous object's retain count will drop back to 1. But it won't reach 0.
There are three solutions:
// OK
self.rate = [[[NSMutableDictionary alloc] init] autorelease];
// Better, has the same effect as statement above
self.rate = [NSMutableDictionary dictionary];
// Clumsy, but works
NSMutableDictionary *tmp = [[NSMutableDictionary alloc] init];
self.rate = tmp;
[tmp release];
Remember, everytime you call alloc/init
or copy
, you get an object that you own. This means you are immediately responsible for calling release
on them. Almost every other method will/should return an object that you do not need to call release
on, except if you called retained
on it to "claim ownership".
In instruments you can see where the leaks is coming from, press the extended details button and select your leak, you will then see what method and file and line the leak is coming from.
精彩评论