Getting EXC_BAD_ACCESS on a method call - iphone

This is really weird in my perspective. I've never seen anything like it. I put all my releases in a method called releaseMethod. Then in my dealloc and didReceiveMemoryWarning, I have [self releaseMethod]; I do this to be more object orienteted and save code because I have a lot of releases. But, occasionally (2 out of 5 times, give or take), I get EXC_BAD_ACCESS on the releaseMethod call in dealloc. The code is below. I didn't know it was possible to have a method call get bad access. I understand memory management and there is no memory involved in calling a method, right?
Thanks in advance.
- (void)dealloc {
[super dealloc];
[self releaseMethod];
}

Put your [super dealloc] at the end of the dealloc so you can first cleanup things in your class before cleaning up things in the superclass (which you might depend on).

If you send the message release to an object that has already been deallocated, this is the message you will get. Check that you aren't overreleasing something in releaseMethod. Remember, when an object is deallocated, it will release objects that it is retaining.
You should also put [self releaseMethod] before you call [super dealloc].

Related

Is it safe to call [self <>] inside viewDidUnload?

Is it safe to do something like:
- (void) viewDidUnload {
[self cleanup] ;
[super viewDidUnload];
}
Because I hear things such as "self" may not even exist in a non-corrupt form when the view is unloading, hence it may be unsafe. Is it safe?
It's totally safe. viewDidUnload gets called in low memory situations when the view controller has temporarily deallocated the view to conserve memory. You just don't want to do anything in there that would access your controller's view property, as that would cause the controller to lazy-load the view again. Other than that, calling methods on self in viewDidLoad is totally safe.
You may be thinking of the dealloc method. I've seen people assert that you shouldn't call methods on self in your init or dealloc methods because your object may be in a partially initialized/released state. I guess the fear is that someone will try to modify or override the method you're calling without realizing that it's being called on a partially-formed object. This risk is increased if you don't set your released properties to nil in dealloc.

Silly memory management issue that has me stumped

I have a property defined as:
#property(nonatomic, retain) UITableView *settingsTableView;
Then in my viewDidLoad method I have:
self.settingsTableView = [[[UITableView alloc] initWithFrame:tableFrame style:UITableViewStyleGrouped] autorelease];
[self.view addSubview:self.settingsTableView];
[self.settingsTableView release];
Then in the dealloc method of the view controller I have:
[settingsTableView release];
When I attempt to do the release from within the dealloc I am getting a "message sent to deallocated instance". I am starting to second guess myself, anybody see anything stupid in what I've done?
Really appreciate the help on this one!
you're calling release on an object you've already autoreleased. Just get rid of the line
[self.settingsTableView release];
and you should be good.
Note that you should keep the release in the dealloc method, since the property calls retain for you, but not release.
Two things. First, you're over-releasing the table view in the first place: the autorelease call negates the need for a manual release afterwards.
Also, in general, what you release in -dealloc are things that you created in -init, -initWithCoder:, or whatever, not loadView or -viewDidLoad. In this case, the method you're looking for is -viewDidUnload; you just have to set self.settingsTableView to nil in that method, and the property setter will handle releasing it if necessary.
Here is the change you need to make.
self.settingsTableView = [[[UITableView alloc] initWithFrame:tableFrame style:UITableViewStyleGrouped] autorelease];
[self.view addSubview:self.settingsTableView];
[self.settingsTableView release];
//^^^ This line is bad no need to release this value until dealloc
//if it is defined as retain or copy
Seems obvious. You have already released with
[self.settingsTableView release];
So why release it again in the dealloc?
I believe the problem is related to your use of autorelease when you are allocating and initializing the UITableView.
You also might have a problem with releasing the settingsTableView right after you use it, vs. in the dealloc method. Anytime you alloc/init an object, you should only release it once.
If you use autorelease, the rules are a little different, so I'd recommend reading up on that again. Also, when you pass objects that you've created off to other things, they may take complete or shared ownership of the object by retaining it, meaning that you may or may not need to release it yourself anymore. The documentation for that should be on the method you're calling (like addSubView).

When does (void)dealloc get called in an AppDelegate?

I understand that instance variables are released in dealloc (as shown below), but when exactly is it called? Are all instance variables released upon app close, or is there an accepted way for them to be deallocated individually as they become unneeded?
- (void)dealloc {
[fred release];
[wilma release];
[barney release];
[betty release];
[super dealloc];
}
Like any other object, the app delegate will be deallocated when no other object has retained it. It's pretty unusual to have an app delegate that doesn't stick around until the app terminates, and as others have pointed out, the app may not bother to release and deallocate anything just before it exits.
I think it's a safe bet that the app delegate would be deallocated if no object other than the app had retained it and you gave the application a new delegate. Aside from that unusual situation, the app delegate's -dealloc method probably doesn't get called very often at all. However, that doesn't mean that you shouldn't implement it correctly -- it's expected behavior, and things could easily change in a future iOS release.

iOS SDK - dealloc implementation - Release child views first?

I am finishing up an iPad application, and for me, that means filling in all of the dealloc methods in my classes.
I have many views in my nib and most of them contain subviews (i.e. UIViews, UILabels, etc.). Should I release the child views before releasing the parent? If the parent view is released, will its child views be released, as well?
Sample:
-(void)dealloc
{
[super dealloc];
[childView release]; // Do I need this if I use the next line?
[parentView release]; // Will this perform the line above?
}
Both childView and parentView are properties of my view controller. Both have been retained.
Anything that you have retained (whether explicitly or through a retained property) needs to be released for the memory management to be balanced.
Also, you should invoke [super dealloc] at the end of your dealloc implementation, not the beginning (for instance, because you might depend on superclass resources still being available at the time).
By the way, saving your dealloc-writing until you're finishing up work on the app is a backwards way to go. I know it seems like house-cleaning work, but the fact is until you're managing memory properly, you're going to have a very skewed view of how your app really performs.
Ideally you should write your dealloc calls as you write your #synthesize statements. In other words, you add a property to your class, you set it up as a retained property, you write its #synthesize and -release code. That way you know your memory management is basically clean (I mean, at the class property level anyway) and you can code with confidence.
Since you specified that you have subviews from a NIB, it sounds like you also may need to pay close attention to the viewDidUnload method.
Any views which are automatically allocated from the nib you can implicitly release by setting the outlet to nil. For example:
- (void)viewDidUnload {
[super viewDidUnload];
self.subviewOutletOne = nil;
self.subviewOutletTwo = nil;
}
Then for any objects which you explicitly retain, you release them in the dealloc method like you are planning to do:
- (void)dealloc {
[myDataArray release];
[coolAnimatedImage release];
[myCustomSubview release];
[super dealloc];
}
Also be sure to check out the LEAKS instrument. This is a random tutorial for using the built in leak analysis tool. There may be others / better ones. It can a pain to get up and running the first time but is completely worth it.

Correct [super dealloc]

Does the order of statements in the dealloc method matter? Does the [super dealloc] need to be at the top of the method? Does it matter?
Also in e.g. viewDidLoad. Should [super viewDidLoad] be at the top of the method?
It ABSOLUTELY matters.
What you do depends on whether you're using Automatic Reference Counting (ARC) or manual reference counting.
Using Manual Release-Retain
Manual Release-Retain (MRR) is default memory management for all versions of Mac OS X, and the only way to handle memory until Xcode 4.2.
With MRR, [super dealloc] should be at the end of your method.
So your code should look like this:
- (void)dealloc
{
[member release];
[super dealloc];
}
The super dealloc actually frees the memory. Think about that. If you access an instance variable after that, like this:
[super dealloc];
[member release];
...it means that the instance variable is potentially invalid. Between the call to super dealloc and the call to member release, theoretically the bytes that stores the member pointer could have been changed to something else!
As Apple explains it in the Memory Management Programming Guide:
The role of the dealloc method is to free the object's own memory, and dispose of any resources it holds, including ownership of any object instance variables.
You do this by disposing of any resources your object holds, and calling [super dealloc]. Which disposes any objects it holds, and calls its super. And so on, and so on, until eventually the root object marks the memory used by the instance itself as free. By the time [super dealloc] returns, your instance has been freed. (Of course, the pointers in it are probably valid, but that's an implementation detail you shouldn't rely on.)
Generally, when constructing (or loading) let the super do the work first. When tearing things down, do your work first.
See also:
dealloc, NSObject Class Reference, Mac OS X Developer Library
Deallocating an Object, Object Ownership and Disposal, Memory Management Programming Guide, Mac OS X Developer Library
With Automatic Reference Counting
Automatic Reference Counting (ARC) is the new way of doing memory management introduced in Xcode 4.2. With ARC, the compiler adds memory management code when compiling your application. It has some wrinkles you'll want to read more about before using it (mostly, limited compatibility with older OS versions).
With ARC, you don't (and can't) call [super dealloc] at all. Instead, [super dealloc] is called when your dealloc finishes.
See also:
LLVM Automatic Reference Counting dealloc
Does the order of statements in the dealloc method matter? Does the [super dealloc] need to be at the top of the method? Does it matter?
It should go at the end. The idea is to say "I've torn down all the bits I've done, so now I'll let my parent class do the same" (recursively)
Also in e.g. viewDidLoad. Should [super viewDidLoad] be at the top of the method?
It should go at the top. The parent class should do what it needs to do to load its view before the subclass loads its parts, because it might rely on something the parent class needs to set up first.