Objective-C - C style string allocation leak?
I have a very simple app. From the main screen I launch a new view ("learn view") that displays an image and a label. on the learn view there is a menu button and a next button. When the user taps the next button, the view updates the image and the label from char * array of C strings. However, when I do this, the instruments allocations sho开发者_如何学JAVAws a forever growing number of allocations that are not reduced when the view is destroyed by clicking the menu button. If I just display the learn view then click menu there is no problem, the allocations go up and then go back down to the prior level, but if I click next updating the label.text, then allocations are made that are not recovered. Instruments reports no leaks. here are relevant code snippets:
LearnVC.h
@interface LearnVC : UIViewController {
IBOutlet UIImageView *imageView;
IBOutlet UILabel *labelView1;
NSInteger page;
}
@property (retain, nonatomic) UIImageView *imageView;
@property (retain, nonatomic) UILabel *labelView1;
@property NSInteger page;
- (IBAction)handleNext;
- (IBAction) gotoMenu;
@end
LearnVC.m
#import ...
char *states[] { "Alabama", "Alaska", "Arizona", ... };
#define maxStates 50
@implementation LearnVC
@synthesize ...
- (void)viewDidLoad
{
NSString *tstring;
self.page = 0;
//test!!!!
tstring = [[NSString alloc] initWithCString:states[self.page] encoding:NSUTF8StringEncoding];
labelView1.text = tstring;
[tstring release];
[super viewDidLoad];
}
- (IBAction) handleNext {
NSString *tstring;
self.page++;
if (self.page > maxStates-1) {
self.page = 0;
}
//test!!!!
tstring = [[NSString alloc] initWithCString:states[self.page] encoding:NSUTF8StringEncoding];
labelView1.text = tstring;
[tstring release];
}
- (void)dealloc
{
[imageView release];
[labelView1 release];
[super dealloc];
}
This seems to occur anytime I update a view without removing (deallocating) it and re-adding it. Is there something with old C arrays that don't copy/release properly. Or some issue with UILabel.text properties that don't release memory? Any help is appreciated.
Thanks beforehand, Neal
I converted it to use NSArray -
I added this to the .h file
NSArray *statesArray;
and @property (retain, nonatomic) NSArray *statesArray;
then in the .m file
in viewDidLoad
NSArray *objects = [NSArray arrayWithObjects:@"Alabama", @"Montgomery",
@"Alaska", @"Juneau" ,..., nil];
self.statesArray = objects;
//I assume that since I didn't init it, I don't need to release objects.
labelView1.text = [self.statesArray objectAtIndex:self.page];in dealloc
[statesArray release];
Then in my handleNext
labelView1.text = [self.statesArray objectAtIndex:self.page];
I run through the entire array, exit, reload, ect. and the allocations climb the first time through but stop climbing after I've been through the list once. This was not the case with the char * array, there must be something else going on, oh well, I'll just have to shed my old C ways and stick to NS/UI classes.
This seems to have solved it. Now I'll work on the image loads and see if the it works the same.
The initWithCString:encoding:
method may make an internal copy of the C string you pass in, but is not guaranteed to free the copy during deallocation. Since the C strings you're passing are constant, and therefore can never be freed, you can instead use initWithBytesNoCopy:length:encoding:freeWhenDone:
to avoid creating the extra copies. For example:
NSString *s = [[NSString alloc] initWithBytesNoCopy:someCString
length:strlen(someCString)
encoding:NSUTF8StringEncoding
freeWhenDone:NO];
Also, the system does a lot of caching, it acts like each control may cache the text it has used. I found that if I ran through the series a couple of times, then then allocations stopped rising, as if it had cached all it was going to. Allocations did not go down to the starting point when exiting learn view, but subsequent runs did not add anymore.
精彩评论