My app is shutting down on a 3G iPhone at ~23mb..
I'm loading a 3mb file into an NSArray as follows... Are str and lines not auto releasing? Any suggestions on a better way to do this?
NSString *str = [NSString stringWithContentsOfFile:path
encoding:NSUTF8StringEncoding error:&error];
NSArray *lines = [str componentsSeparatedByString: @"\n"];
[self parseDictLines:lines];
- (void)parseDictLines:(NSArray *)lines {
int i = 0;
NSMutableArray *arr = [[[NSMutableArray alloc] init] autorelease];
NSMutableArray *word_list = [[NSMutableArray alloc] init];
for (NSString *line in lines) {
i++;
[arr addObject:line];
if ( i == 3 ) {
i = 0;
[word_list addObject:[arr copy]];
[arr removeAllObjects];
}
}
self.mDict = (NSArray*)word_list;
[word_list release];
}
EDIT - The app is < 1mb before this code or if I skip this code. It is 22mb after it runs... So it can't be the temp variables.. Its usable until I do something that adds another 1mb at which point it bails.
EDIT2 - The NSString *str of the file is 5.9mb - I assume due to the way the string is encoded in memory is twice as big as the UTF8 file. The *lines array is also that size.
However str was not getting released immediately until I added the auto release pool. Running with instruments it takes 5 minutes for the NSArray *lines to fill up, after [lines release] is called it took about 3 minutes before the memory started going away and 5 minutes after that before the memory used by the *lines array was down to < 1mb. My mDict array is 14mb. I don't know why since its not that much different than NSArray *lines which was 6mb...
The below code solves my problem which obviously was that I was hitting the memory limit before the str and lines memory was released. Now that str gets released right away that frees up 6mb and its not possible for the user to go over the limit now while this code is loading in the background.
BUT - Why is the OS dumping my app when I've already auto released 12mb? Wouldn't it clean up anything that needs to be auto released on its own?
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
NSArray *lines = [[str componentsSeparatedByStrin开发者_Go百科g: @"\n"] retain];
[pool drain];
[self parseDictLines:lines];
[lines release];
you're over-retaining the arr
variable. You should replace
[word_list addObject:[arr copy]];
with
[word_list addObject:arr];
One approach would be to set up an NSAutoRelease pool before the loop, that you drain right after [arr removeAllObjects]
. Draining a pool is the same as releasing it, so after that you have to alloc/init the pool again.
Run it through Instrument's Allocations instrument and you should be able to see where the memory is going.
精彩评论