Where the Memory is Leaking because showing leakage - objective-c

In my Code showing 2 places memory leakage please see and Help me.
1.FIRST
UIButton *push = (UIButton *)sender;
NSString *string = [NSString stringWithFormat:#"%#",[push currentTitle]];
NSArray *chunks = [[NSArray alloc]initWithArray:[stringcomponentsSeparatedByString:#"-"]];
list = [[NSMutableArray alloc]initWithArray:chunks];
(NSMutableArray *list;)
[chunks release];
2.SECOND
Here is The Source Code First
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSURL *url = [[NSURL alloc]initWithString:#"http://www/absdf.com/myXML.xml"];
self.parser = [[NSXMLParser alloc]initWithContentsOfURL:url];
[parser setDelegate:self];
[parser parse];
[parser release];
[url release];
[pool drain];
while i am excuting this code and with this Instruments Tools on line number : 2 show memory leakage with heaviest backtraces.
So please let know the Reason .?

In addition to the other answers your pool should be released
NSAutoreleasePool *pool = [NSAutoreleasePool new];
//... then
[pool release];

Obviously, list = [[NSMutableArray alloc]initWithArray:chunks]; is never released.

self.parser = [[NSXMLParser alloc]initWithContentsOfURL:url];
alloc/init returns a retained object, and if you your parser property is declared with retain attribute, then you are over retaining it. It should be:
self.parser = [[[NSXMLParser alloc]initWithContentsOfURL:url] autorelease];
P.S. Make sure you are doing proper memory management to your list instance variable. Just to be sure you better use properties.

list should be release somewhere, maybe in dealloc
- (void)dealloc {
[list release];
[super dealloc];
}
parser = [[NSXMLParser alloc]initWithContentsOfURL:url];
or
NSXMLParser *tempParser = [[NSXMLParser alloc]initWithContentsOfURL:url];
self.parser = tempParser;
[tempParser release];

Related

memory menagement in ios

Can anybody explain me why does the case1 and case2 crashes while the others does not in case of non-ARC?
Case1:
NSString *rr = [[NSString alloc] initWithString:#"AB"];
[rr release];
[rr autorelease];
Case2:
NSString *rrr = [[NSString alloc] initWithString:#"AB"];
[rrr autorelease];
[rrr release];
Case3:
NSMutableString *rr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rr1 release];
[rr1 autorelease];
Case4:
NSMutableString *rrr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rrr1 autorelease];
[rrr1 release];
Case5:
NSArray *rr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rr3 release];
[rr3 autorelease];
Case6:
NSArray *rrr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rrr3 autorelease];
[rrr3 release];
Case7:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 release];
[rr2 autorelease];
Case8:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 autorelease];
[rr2 release];
All are are incorrect because eventually all will be released twice, but some may coincidentally not crash.
The alloc allocates the object with a retain count of 1. release decreases the retain count 1. autorelease eventually decreases the retain count 1. That means that all are over released.
But as #Chuck mentions some instances are constants, are created at compile time and never released so release and autorelease can be called to many tines with no crash.
String constants are one instance of this this where over-releasing will not cause a crash:
NSString *s = #"aa";
Even over-releasing this is OK because the compiler is smart enough:
NSString *s = [NSString stringWithString:#"aa"];
But you will get a warning from the current LLVM compiler that using stringWithString with a literal is redundant.

Force release an autorelease object

Can I force an Autorelase object by calling a release without autorelease pool like that:
NSString *myString = [[[NSString alloc] init] autorelease];
[myString release];
Normally it's like that:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *myString = [[[NSString alloc] init] autorelease];
[pool release];
The first sample will crash, since the string will get over-released. If you want to have control over the lifetime of your autoreleased objects, the correct approach is what your second sample does – create a local autorelease pool that you can drain when you want.
Your code will crash because global auto release pool will try to release the object later. Results in malloc double free error
You can do this:
NSString *myString = [[[NSString alloc] init] autorelease];
Or this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *myString = [[[NSString alloc] init] autorelease];
[pool release];
But not this:
NSString *myString = [[[NSString alloc] init] autorelease];
[myString release];

[NSDate descriptionWithLocale:[NSLocale systemLocale]] leak?

Using instruments I found a strange problem regarding memory leaks. My app has a log mechanism which record events through the app and the whole communication with the server(request-response). Each event object that is been wrote has a timestamp. This timestamp is get as follows:
[NSDate descriptionWithLocale:[NSLocale systemLocale]]
Using instruments, I saw that descriptionWithLocale cause leaks.
Below is the code:
-(id)initEvent:(NSString*)eventStr details:(NSString*)detailsStr{
eventString = [[NSMutableString alloc] initWithString:eventStr];
detailsString = [[NSString alloc] initWithString:detailsStr];
date =[[NSMutableString alloc] init];
NSDate* currentDate = [NSDate date];
NSString *dateDescStr = [currentDate descriptionWithLocale:[NSLocale systemLocale]];
[date appendString:dateDescStr];
return [super init];
Thanks,
Alex.
Are you sure it's descriptionWithLocale that's causing your memory leak? You're not using the property accessor/mutator to set your class properties and you're releasing them in a method other than your dealloc method, which is going to cause issues. At the least, you're violating the basic memory management rules by allocating eventString, detailsString, and date in initEvent (which is then the owner, because you don't use a property accessor/mutator) and releasing them in the eventDictionary method, which is not the owner.
I would start by trying the following (assuming all your properties have the retain attribute):
-(id)initEvent:(NSString*)eventStr details:(NSString*)detailsStr{
this.eventString = [[NSMutableString alloc] initWithString:eventStr];
this.detailsString = [[NSString alloc] initWithString:detailsStr];
this.date =[[NSMutableString alloc] init];
NSDate* currentDate = [NSDate date];
NSString *dateDescStr = [currentDate descriptionWithLocale:[NSLocale systemLocale]];
[date appendString:dateDescStr];
[eventString release];
[detailsString release];
[date release];
return [super init];
}
Also remove your release calls from eventDictionary and add them to the dealloc method, as per the standard memory management pattern.
Give that a try and see if it helps. Let me know if I can clarify anything.
Thanks for your solution. It works great. Indeed not descriptionWithLocale was the cause of the leak, but my own memory rule implementation (was 1 year ago :( ). Strange that instruments was pointing out to that method call.... See how my class looks now:
#implementation EventItem
#synthesize eventString, detailsString, date;
-(id)initEvent:(NSString*)eventStr details:(NSString*)detailsStr{
if((self = [super init])){
self.eventString = [[NSMutableString alloc] initWithString:eventStr];
self.detailsString = [[NSString alloc] initWithString:detailsStr];
self.date =[[NSMutableString alloc] init];
NSDate* currentDate = [NSDate date];
NSString *dateDescStr = [currentDate descriptionWithLocale:[NSLocale systemLocale]];
[date appendString:dateDescStr];
[eventString release];
[detailsString release];
[date release];
}
return self;
}
-(NSMutableDictionary*)eventDictionary{
if(!dictionary)
dictionary = [[NSMutableDictionary alloc] init];
else
return dictionary;
[dictionary setObject:self.date forKey:#"Event"];
[dictionary setObject:self.date forKey:#"Date"];
[dictionary setObject:self.detailsString forKey:#"Details"];
[dictionary setObject:self.eventString forKey:#"EventDescription"];
return [dictionary autorelease];
}
-(void)dealloc{
// NSLog(#"dealloc called in EventItem");
[eventString release];
[detailsString release];
[date release];
[super dealloc];
}
#end
Now, another problem that i have is regarding to some image loaded via "loadWithContentsOfFile:"
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.rowHeight = OC_CELL_HEIGHT;
self.tableView.backgroundColor = [UIColor clearColor];
UIImage* backgroundImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"TableBg" ofType:#"png"]];
UIImageView* background = [[UIImageView alloc] initWithFrame:self.tableView.frame];
background.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
background.image = backgroundImage;
[background sizeToFit];
[backgroundImage release];
[self.tableView setBackgroundView:background];
[background release];
[self.tableView setAutoresizesSubviews:YES];
selectedOCData = nil;
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin;
}
The line :
UIImage* backgroundImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"TableBg" ofType:#"png"]];
leaks 98% and the haviest backtrace is 240 kb. I attached a screenshot with instruments for this. Is there a problem not with the actual call of initWithContentsOfFile, but with the tableView which is not deallocated correctly?(My class is a tableViewController).
Thanks,
Alex.

Objective-C Memory Management Alchemistry: Code causes a leak after being put in a class

I came to Objective-C from C++ so I still sometimes has problems understanding memory management of Objective-C. I have a following problem now - XCode Analyzer tells me that object *data causes leaks further in code.
- (void)loadSettings
{
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSData *data = [[NSMutableData alloc]
initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
initForReadingWithData:data];
// object *data is no longer referenced at this point and has a retain count of +1 (object leaked)
AppData *settingsData = [unarchiver decodeObjectForKey:kDataKey];
if (nil != settingsData)
{
customerVoiceActive = settingsData.customerVoice;
}
[unarchiver finishDecoding];
[unarchiver release];
[settingsData release];
}
}
What drives me crazy is that exactly the same code (except naming) perfectly works and causes no leaks, being placed in applicationDidFinishLaunching:
//load app data
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSData *data = [[NSMutableData alloc]
initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]
initForReadingWithData:data];
AppData *appData = [unarchiver decodeObjectForKey:kDataKey];
bCustomerVoice=appData.customerVoice;
[unarchiver finishDecoding];
[unarchiver release];
[data release];
}
What's the difference?
In code sample 1) you release settingsData, while in codesample 2) you are releasing data . Changing that line should solve your issue.
You forgot to release NSData *data.
Add the following line after [settingsData release];:
[data release];
The "exact same" code contains an extra line:
[data release];
settingsData should NOT be released, because it was not obtained through a method that implies that you own the returned object. However, you MUST release data, because you allocated it yourself, and this implies ownership.

NSString memory leak?

I'm turning around and around with the following code giving me a memroy leak in the pics object apparently linke to the object imageName.
for (int i = 0;i<[potatoesIndexesArray count];i++){
int imageNumber = [[potatoesIndexesArray objectAtIndex:i]intValue];
NSString *imageName = [[NSString alloc] initWithFormat:#"texture%d",imageNumber];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:#"png"]];
//UIImage *imageHighlighted = [[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:imageName ofType:#"png"]];
NSArray *pics = [[NSArray alloc] initWithObjects:
[self maskImage:image withMask:[mainDelegate.masksArray objectAtIndex:i]],
[self maskImage:image withMask:[mainDelegate.masksArray objectAtIndex:i]],
imageName,
nil]; // pics becomes owner of objects
[textures addObject:[pics retain]]; //textures becomes owner of pics. as a release occurs later. we must retaint pics to keep it available in textures.
[imageName release];
[image release];
[pics release];
//[imageHighlighted release];
}
I've read the Apple doc on memory management bu I can't find what I did wrong there ... any idea ??
Cheers,
Tibi.
If textures is a NSMutableArray, then your [textures addObject:] call already sends a retain to pics. So, the code should be:
[textures addObject:pics];