NSDate memory leak - xcode

I have searched SO among other fora for the answer to this, but whatever I try, it does not seem to get rid of my memory leak. Does anybody have any suggestions?
I get a memory leak of 16 bytes per NSDate in my ViewController every time I present it.
-(void)initialise:(id)sender withDate:(NSDate *)date withMinimumDate:(NSDate *)minimum {
delegate = sender;
self.originalDate = [[NSDate alloc] init];
self.originalDate = date;
self.minimumDate = [[NSDate alloc] init];
self.minimumDate = minimum;
}
- (void)dealloc {
[self.originalDate release];
[self.minimumDate release];
[super dealloc];
}
I have tried releasing and/or making the NSDates nil before allocating them for the first time, and setting them to nil in the dealloc method.
They are declared as nonatomic and retained properties in the Header.
Have I missed something basic here or is there a more complex answer?

You are doing an alloc/init of a NSDate for originalDate, but then immediately abandoning it and setting it equal to the date parameter, possibly leaking the NSDate you created. You're doing this with minimumDate, too.
At a minimum, remove those two lines that do the alloc/init of the two respective NSDate objects that you subsequently abandon in favor for the parameters to the initialise method.
By the way, this problem (and the dealloc problem) would have been highlighted for you if you employed the static analyzer ("Analyze" on "Product" menu or press shift+command+B):
When writing manual reference counting code, the static analyzer is invaluable for identifying issues. You really should have a clean bill of health from the analyzer. You can click on the blue icons and it will often expand with the descriptions and arrows that I show in the above screen snapshot.
Note, this also highlighted the inappropriate use of self.originalDate (instead of _originalDate, or whatever the backing instance variable is) in your dealloc method. As I mentioned in my earlier comment, you should not use accessor methods in dealloc method.

These two lines are creating references to objects that are never released.
self.originalDate = [[NSDate alloc] init];
self.minimumDate = [[NSDate alloc] init];
Seeing as you instantly overwrite these properties with new values, you just need to delete these two lines (which are redundantly allocating NSDate objects that are never used) and your leak should go away.
You should also check whether delegate is properly memory managed too, as I see no release in dealloc for the delegate variable.

Related

No ARC, the app didn't crash without releasing the object that created by hands

Currently I didn't use ARC in my app, and I tried to create a NSAlert object as a local variable, at the end of function, I didn't release it.
I expected that the app crash with that, the function code is here.
#define GLOBAL_VARIABLE 0
NSString *msgText = [self.defaultValueTextFiled stringValue];
NSString *informativeText = #"Informative Text";
#if !GLOBAL_VARIABLE
NSAlert *alertView = nil;
#endif
if (alertView == nil)
{
alertView = [[NSAlert alloc] init];
[alertView setMessageText:msgText];
[alertView setInformativeText:informativeText];
NSTextField *accessory = [[NSTextField alloc] initWithFrame:NSMakeRect(0,0,200,22)];
[accessory setStringValue:#"accessory result"];
[alertView setAccessoryView:accessory];
}
NSView *accessory= nil;
NSInteger result = [alertView runModal];
if (result == NSAlertAlternateReturn)
{
accessory = [alertView accessoryView];
if (accessory != nil)
{
NSTextField *txtFiled = (NSTextField *)accessory;
NSLog(#"%ld", [accessory retainCount]);
NSString *str = [txtFiled stringValue];
NSLog(#"%ld", [accessory retainCount]);
[self.resultValueTextField setStringValue:str];
NSLog(#"%ld", [accessory retainCount]);
}
}
Questions:
(1) There is no [alertView release] in the end, why not crash? It has even no leaks.
(2) Refer to here , the accessory view shouldn't be release. However, I tried to release the view before [alertView runModal], then get its stringValue later, that could works. Why?
(3) The return value of function retainCount is interesting. When I created the alertView object, the retainedCount of alertView is 3. (Why?)
Before [alertView setAccessoryView:accessory], the accessory's retainedCount is 1, then it changed to 2 after executing it. That's normal and right. However, the log result for the above code, they're 20, 21, 22. How did they come from?
Thanks for your attention!
It does leak. Put a breakpoint on dealloc (or create a subclass of NSAlert and add a log statement to dealloc) to show this
The accessry view should be released. You alloc it and then it would be retained by the alertView
Here's a concise guide on when to use retainCount.
The rules for memory management are generally quite simple. Most problems come from overthinking them and trying to guess what other parts of the system are going to do, rather than just following the rules as written.
The first rule of Memory Management:
Use ARC.
If you cannot follow rule one (for instance, you are developing for OS X 10.5 as I do), then here are the rules:
You must balance each call you make to +alloc…, +new…, -…copy… or -retain with a call to -release or -autorelease.
That's really it. Everything else is really just commentary to help you follow that rule. So, you called [NSAlert alloc] and [NSTextField alloc], you need to call release on those objects.
Why doesn't it crash?
Because a leak is not going to crash unless it causes you to run out of memory.
Why doesn't it leak?
The most likely cause is that you're only running it once and then expecting Instruments to detect the leak. It may not show up if you only run it once. It depends on how NSAlert is internally implemented. Instruments finds leaks by walking all the pointers in the system and determining if any accessible pointers still reference a piece of allocated memory. There are many cases when a "leak is not a leak."
But this also suggests you're not running the static analyzer, because the analyzer should definitely have detected that leak. Run the static analyzer (Cmd-Shift-B) all the time and clean up what it finds.
the accessory view shouldn't be release.
That's not what the link you reference says. You shouldn't add an extra release. But in the referenced code, you'll notice that they release the view to balance their own +alloc.
… retainCount …
Never use -retainCount. Not even for debugging. Not even for anything else. There is no point at which retainCount is going to return you a piece of information that is going to be more enlightening than confusing. Why is it greater than you think it should be? Because other objects are retaining the alert view? Which objects? That's not your business. That's an internal implementation detail, subject to change. It could be pending autorelease calls, which show up temporarily as a "too high retainCount". It could be the run loop. It could be an internal controller. It could be anything. Calling retainCount tells you nothing useful.
Now that you understand manual memory management, switch to ARC and think about object graphs rather than retain counts. It is a much better way to deal with memory.

Need Help Resolving a Memory Leak Once it is Located Using Instruments

I have an application in Xcode 4.6 that connects with Facebook. I have noticed that every so often when the application goes into the background and returns to the foreground, there are occasional crashes at varying points in the application. Being inconsistent, the crashes were difficult to analyze, so I tried using instruments to identify memory leaks. I am quite new to iOS, and although I was able to successfully determine that I do have memory leaks, and I can even see which methods are triggering them, I find myself thinking, "well what now?" In other words, I see where the problem is, but yet I can't identify it. I am hoping if I highlight an example, someone can shed some light.
**Here is what I am looking at in instruments:
Just looking at the first leaked object in the list:
Leaked Object = "FB Session"
Responsible Frame =
+[FBSession openActiveSessionWithPermissions:allowLoginUI:allowSystemAccount:isRead:defaultAudience:completionHandler:]
I interpret this to mean that there is some leaked object existing inside of this method. Is that correct? The implemented method exists in my App Delegate and looks like:
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_about_me",
#"read_friendlists",
nil];
//IMPLEMENTED METHOD
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
At this point, I am not sure what I need to do, or what about this method could even be causing a leak. I have looked though memory leak tutorials, but they only got me to the point of locating the problem, but stop short of helping me figure out how to solve it. Any help is appreciated.
Generally you shouldn't pass self to block as block retains it. It seems, that FBSession also retains completionHandler, so it becomes a retain cycle.
In order to break it, use one of the following constructions:
__weak FBSession *zelf = self; // OK for iOS 5 only
__unsafe_unretained FBSession *zelf = self; // OK for iOS 4.x and up
__block FBSession *zelf = self; // OK if you aren't using ARC
and then
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[**zelf** sessionStateChanged:session
state:state
error:error];
}];
See this post for more complete explanation of what retain cycles are.

Converting self-releasing objects to ARC

OK, so Apple brought ARC to us, which is great. After refactoring my Application to ARC almost everything works fine and it is a lot easier now to develop and maintain.
There is just one problem I still can't figure out.
My job management program shows different detail information of proposals, orders and so on in their own windows. So I have a special class where WindowControllers gets allocated and initiated with initWithWindowNibName and then the window is shown with showWindow:
DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:#"ThePorposalWindow"];
[proposalWindowController showWindow:nil];
Before ARC the Instance of the WindowController did the release like shown in the documentation:
- (void)windowWillClose:(NSNotification *)notification
{
[self autorelease];
}
But now with ARC this is not possible anymore and what makes it even worse, in my special class where the WindowController is allocated and initiated, the same windowController is released by ARC because there is no pointer to the windowController.
My idea was to copy the windowController into an mutuable array:
[proposalWindowArray addObject:proposalWindowController];
[[proposalWindowArray lastObject] showWindow:nil];
And in the windowControllers delegate method windowWillClose I post a notification to my special class:
- (void)windowWillClose:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"ProposalWindowWillClose" object:[[self window] windowController] userInfo:nil];
}
In my special class I listen to the notification and remove the object from the array:
- (void) proposalWindowWasClosed: (NSNotification *) notification
{
[proposalWindowArray removeObjectIdenticalTo:[notification object]];
}
It works, but I still do not believe that this is the correct way.
Does anybody has the same problem or a tip to make it better?
I'd probably use a delegate approach rather than notifications. Generally it is better to have an external object that keeps track of the open windows. Self-retaining objects, like your old system, break the basic points of object ownership and make it hard to find things (such as "give me a list of open windows"). Non-Singletons that are just "floating" out there often come back to bite you in your architecture (I've had to fix this often enough).
That said, sometimes self-ownership is at least convenient, and at worst not-the-end-of-the-world. So self-own. The only difference is that you need to do it explicitly rather than matching a leak and an over-release (which is what your old code was doing).
Create a private strong property. Assign self to it. That will create a retain loop that will keep you around until you set the property to nil.
I think your alternative approach should be correct, but I don't think you need the second notification. You should be able to do:
- (void)windowWillClose:(NSNotification *)notification
{
[proposalWindowArray removeObjectIdenticalTo:self];
}
Assuming the "proposalWindowArray" is a static NSMutableArray.
Without hacks, there is no elegant way to keep an object retained other than having a strong reference to it in some other object. For example, you could keep a static NSMutableArray/NSMutableSet, add your controller there, and remove it in windowsWillClose:. This will be shorter than posting a notification. To make this reusable, create a WindowControllerRegistry singleton with an array, where you add controllers like this one, and which will automatically listen to NSWindowWillCloseNotification and remove them from its array thus releasing ownership.
As a quick workaround, you could perform retain/autorelease calls from non-ARC file:
my_retain(self);
my_autorelease(self);
// ArcDisabled.mm
void my_retain(id obj) { [obj retain]; }
void my_autorelease(id obj) { [obj autorelease]; }
I had this same issue when I switched to ARC. Your solution works, but you're making it too complicated. You can essentially do what you were doing before by having the window release itself when it closes, but in an ARC compatible manner.
The solution is to simply create a property of your class within the class itself. For your example, in DetailWindowController, you would add the following property:
#property (strong) DetailWindowController *theWindowController;
Then when you create the window with your code above, add one line like so:
DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:#"ThePorposalWindow"];
[preferenceController setTheWindowController:proposalWindowController];
[proposalWindowController showWindow:nil];
Then finally, to have ARC release the window when it is closed like you did with the autorelease pre-ARC, in the DetailWindowController class, simply do:
- (void)windowWillClose:(NSNotification *)notification
{
// Let ARC tear this down and clean it up
[self setTheWindowController:nil];
}

Why is app crashing in iPhone simulator; how can I fix this?

I'm working on an app that uses a navigation controller. When I build, I get no errors or warnings. I've defined a method myMethod in FirstViewController.m file, then in viewDidLoad I call the method with [self myMethod];.
When I built and ran from the Console, I got nothing. So I put NSLog() statements like so:
-(void) viewDidLoad {
NSLog(#"Entering viewDidLoad");
[self myMethod];
NSLog(#"Called myMethod");
[super viewDidLoad];
}
The Console never returns the second NSLog statement, leading me to believe that the app crashes while calling the method.
I've tried this with the simulator set to iOS 4.0.1 as well as iOS 4.1. I'm building against the iOS 4.1 SDK. I really appreciate any help you can offer.
Update: I ran the Debugger, which seems to show the problem being in myMethod. I only make it through a few lines of code in that method before I receive "EXC_BAD_ACCESS". The lines of code are:
-(void)myMethod {
NSMutableArray *someStuff;
NSMutableArray *someMoreStuff;
stuffSections=[[NSMutableArray alloc] initWithObjects:#"Some Stuff",#"Some More Stuff",nil];
someStuff=[[NSMutableArray alloc] init];
someMoreStuff=[[NSMutableArray alloc] init];
[someStuff addObject:[[NSMutableDictionary alloc]initWithObjectsAndKeys:#"Item Name",#"name",#"Item Picture.png",#"picture",#"http://theurl.net/",#"url",#"1",#"itemCode",nil]];
But it appears that I can't get past this first attempt to add something to the someStuff array.
Looks like there is a problem in "myMethod". If I had to guess, I would say you are trying to reference an object that was auto-released and not retained.
You're missing the alloc when initializing someStuff and someMoreStuff. It should be
someStuff = [[NSMutableArray alloc] init];
someMoreStuff = [[NSMutableArray alloc] init];
Have you cross checked the two MutableArrays? Do they have been allocated successfully? You get "EXC_BAD_ACCESS" when the app got into a corrupted state that is usually due to a memory management issue. I guess the arrays are not allocated.
Try allocating this way.
NSMutableArray * someStuff = [[NSMutableArray alloc]initWithCapacity:3];
NSMutableArray * someMoreStuff = [[NSMutableArray alloc]initWithCapacity:3];
add a breakpoint there are check in the debug area and confirm whether they are being allocated successfully. If there is a memory to each of these array, then they are allocated.

NSDate* getting corrupted after a few render cycles. Why?

I have a general timer with a 1.5 second interval (the render cycle).
I have a class with an NSDate* member/property (nonatomic, retain).
I set this date by calling [callingClass setDate:expirationDate];
Now... a couple of render cycles this NSDate is valid. However, around the 3rd cycle the value of this variable gets corrupted, it seems.
When i set a break-point i notice that i can hover the mouse and see the data displayed properly (when its valid). But when its invalid i either see "out of scope", some weird strings (looks kinda like library file names or something), or in rare cases the debugger wont show me the value of any variable (i hate debugging in xcode).
So this is why i think this variable is getting corrupted somehow.
Should i be setting this synthesized property as (nonatomic, retain)? Or should it be declared as something else?
I think i found the problem.
I have a method called:
- (NSDate*) getNSDateFromString:(NSString*)stringDate;
When i called this i was doing NSDate *date = [self getNSDateFromString:expirationString];
This was causing the behavior i described above.
Then i changed it to the following which eliminated the crashings:
NSDate *date = [[self getNSDateFromString:expirationString] retain];
// do something with the date here...
[data release];

Resources