Using self on iVars in dealloc? - iphone

Usually I write my dealloc to look like this:
- (void)dealloc {
[coffeeList release];
[super dealloc];
}
But today I typed (see below) and was a little puzzled why I got an error running the code through the CLANG static analyser. As I say I don't usually add self to iVars in dealloc, but was just a little curious when I spotted this as to what was going on.
- (void)dealloc {
[[self coffeeList] release];
[super dealloc];
}
gary.

I'm just guessing that clang notices [self something] release (or [self.something release]) goes against the memory management conventions. An object returned from a method not having "new", "init", or "copy" in its name should be autoreleased, so releasing it again would appear to be an over-release error.

Because that's really bad form, and goes against how you should be doing things. CSA doesn't just check for semantic errors, it also checks that you're doing things the way you should be. Where the way you should be, is the way things are done in the documentation.

Is coffeeList declared as a property (and set to retain)? Then you should probably do:
[self.coffeeList release];

Related

Objective C ARC equivalent for self?

What is the equivalent keyword i can use in the place of self in ARC enabled projects?
ex:- [self mymethod]; what is ARC equivalent of this method call?
I don't quite get it? Why ARC should have different syntax for method calls? It is an automatic memory management, where in most cases you won't need to use retain/release, nothing more. So it would look like this:
[self mymethod];
In ARC(Automatic Reference Counting),you don't need to release or retain. It has nothing to do with calling methods!
ARC - Automatic Reference Counting implements automatic memory management for Objective-C objects and blocks, freeing the programmer from the need explicitly insert retains and releases. Since this is handled at compile time, no collector process is need to continually clear memory and remove unreferenced objects.
For calling a method, you still do it this way:[self mymethod];
it's still the same
[self myMethod];
But in ARC environment, IIRC, you need to do it like this: (I don't know if this is the source of your question, but when I migrated the first time to ARC, I get compile error if I'm not doing this).
#interface myController()
- (void)myMethod; // you need to declare the method here, if you haven't declared it on the .h
#end
#implementation
- (void)viewDidLoad
{
[super viewDidLoad];
[self myMethod];
}
- (void)myMethod
{
NSLog(#"!");
}
#end
hope this help

Releasing ivars in Objective-C

OK, looking at this:
Apple docs: Declared Properties
If you scroll down to dealloc it reads:
"Typically in a dealloc method you should release object instance variables directly (rather than invoking a set accessor and passing nil as the parameter), as illustrated in this example:"
- (void)dealloc {
[property release];
[super dealloc];
}
"If you are using the modern runtime and synthesizing the instance variable, however, you cannot access the instance variable directly, so you must invoke the accessor method:"
- (void)dealloc {
[self setProperty:nil];
[super dealloc];
}
Now, I must own at least 15 to 20 books on iOS development. I can't say that I have ever seen any code in these books proposing that one do anything other than:
[someproperty release];
Is there a compelling reason to edit a bunch of files of code that works perfectly well to adopt Apple's recommendation? How about future work? Or, are they pretty much equivalent?
Apple's document appears to apply only if you have synthesize-by-default turned on. If you have it turned off, which seems to be the default case, you need #synthesize, which gives you access to variables directly.
Personally, I do:
#synthesize someProperty=_someProperty;
just so I can then do:
- (void)dealloc {
[_someProperty release];
[super dealloc];
}
See Jeff LaMarche's blog for more.
On the modern runtime, you no longer have to declare instance variables for properties, nor do you have to write #synthesize in the implementation. If your code already has the instance variables declared, then there's no reason to replace code that calls release with a call to a set accessor (the first quote you pasted even states that).

Objective-C memory management - pretty sure I'm doing this all wrong

After 3 hours or so, I've finally managed to fix a memory leak in a view controller. The leak was caused by a UIPickerView that has its property set to 'retain' in the header file.
The following code managed to fix it:
- (void)viewDidLoad {
[super viewDidLoad];
myPicker = [[[UIPickerView alloc] initWithFrame:CGRectZero]autorelease];
}
- (void)dealloc {
[super dealloc];
[myPicker release];
myPicker = nil;
}
Please don't tell me how shocking this code is... I know it's bad. I've got a release, and an autorelease. Problem is, if I change or remove any part of the above, the memory leak returns.
I though I knew how objective C memory management works, obviously not...
Why does the above code fix the memory leak, and what might a correct version of the code look like?
-
EDIT:
If anyone has the same problem, or is interested - the problem was that one of the other objects in my class was set to 'retain' rather than 'assign'. (If you don't own an object, it should have the property assign, not retain).
Like Cannondale said, removing the extra retain fixes everything, and only one release is necessary.
You must be doing a retain on myPicker somewhere else in your code. Your myPicker allocation line will release that memory as soon as the stack unrolls for the viewDidLoad call (that is what the autorelease is telling it do do).
You must be doing a retain somewhere after that point, if not then your [myPicker release] will be trying to free unallocated memory with unpredictable results.
What you should be doing is allocating the memory in viewDidLoad (so remove the autorelease). Make sure you don't retain the object anywhere else and release myPicker from the dealloc.
Also ... what bbum said re the dealloc ;)
What Cannonade said. This should work:
myPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
Your dealloc is busted, too. Call to super always has to be last (think about it) and that can lead to undefined behavior.
- (void)dealloc {
[myPicker release];
myPicker = nil;
[super dealloc];
}

objective-c releasing uninitialized class members in dealloc method

Regarding over-releasing. Say I have a instance variable defined in Test.h
NSString *mystring;
In my implementation Test.m I do not initialize the variable mystring anywhere. But I release it in dealloc:
-(void)dealloc {
[mystring release];
}
Is this now over-released? I've been doing the following in dealloc to avoid any issues, however, is this really necessary?
-(void)dealloc {
if (mystring) [mystring release];
}
It seems that [nil release] shouldn't do anything, can someone verify this with class members?
There is no way to over-release something that never existed in the first place.
Instance variables are initialized to nil and, thus, [mystring release] is messaging nil which is just fine in Objective-C.
Your -dealloc methods do need to call [super dealloc] at the end, though.
First, why are you creating a variable at the class level that you're not initializing anywhere?
As this post is tagged iphone and it's IMPORTANT to manage your memory in the iphone environment it's always a good idea to release something if you've defined even if you don't assign it.
You can call release on an uninitialized variable without any problems, and be sure to [super dealloc]

Best practice in cleaning up memory for iPhone apps?

I have seen sample source code around that uses different ways of releasing/dealloc'ing objects, so I was wondering which way is deemed the "best" one. A few options on -dealloc:
1) Release objects
- (void)dealloc {
[obj1 release];
[obj2 release];
[super dealloc];
}
2) Set objects to nil
- (void)dealloc {
self.obj1 = nil;
self.obj2 = nil;
[super dealloc];
}
3) De-allocate objects directly
- (void)dealloc {
[obj1 dealloc];
[obj2 dealloc];
[super dealloc];
}
Which way is the best one? Pros and cons for each?
Method 1 is the only recommended method. It's also good practice to set them to nil AFTER you've released them.
Method 2 only works for properties that manage their own object/value retaining, so it's not universally applicable. And if you implement your own setter method that performs other actions when the property changes, you may get undesired side effects by calling it in [dealloc].
Method 3 violates the reference-counting principle because it will deallocate the objects even if something else has a [retain] hold on them, so when the other objects access them next, your program will crash. You're never supposed to call [dealloc] directly -- let the runtime call it when the last owner calls [release].
If obj1 and obj2 are properties using #synthesize-d accessors, then method 1 and method 2 are equivalent. If either of those two conditions is not true then the effect is rather different. If they're not properties, then method 2 just sets the pointers to nil without doing anything that would deallocate the objects. And if they are properties but you've implemented your own setter methods, method 2 calls those methods with "nil" as the argument. Whether that's equivalent to method 1 or not depends on how you've implemented those methods. If your custom setters do anything significant when the argument is nil, method 2 would ensure that this code executed.
As Marco said, method 3 is just plain wrong. If you've seen sample code doing that then the author may not actually know what they're doing.