I was trying to track a strage memory allocation bug so I overrode the retain and release methods of my class. I noticed that when assigning an instance of this class to a property of another, the retain count of the object increased, but my redefined retain was never called.
How can this be possible? Are (retain) properties retaining the object without calling retain?
In my machine, the overridden retain was called. (I'm using 10.6.4. I checked this both on GCC 4.2.1 and clang 1.5.)
Could you post your code?
Internally, the synthesized setter for a retain property uses objc_setProperty, the source code of which is available here.
As you see, eventually it calls [newObject retain] when the property uses retain.
Is garbage collection turned on? I don't believe retain is called under GC.
if you don't use self (self.yourproperty), it won't increase the retain count.
I wouldn't be surprised if synthesized properties would modify the retain count without calling retain or release.
Related
I have seen report that if a delegate uses assign instead of weak, the app crashes. Why?
Example: RestKit
With ARC a weak ivar will be automatically set to nil when the ivar object is deallocated. That means that if your delegate is destroyed and you try to message the delegate you'll just message nil, which has no effect. If the delegate ivar was merely assign then you would message some chunk of memory that no longer contained a valid object.
The only difference between assign and weak is that weak does extra work to avoid some common crashing bugs. The drawback, however, is that assign has much better performance than weak.
Specifically, when an object is released, any weak property pointing to it will be set to nil. Any assign property pointing to it will be left pointing at the object that is no-longer used.
And some other object is likely to be placed at the same location in memory as the old object, so suddenly instead of an instance of MyDelegate you might have a UIImage object in the same location in memory, or perhaps a float value, or anything at all.
So you should always use weak, for everything. But if you run into performance problems, check if weak is the cause, and consider switching to assign after learning how to avoid those crashing bugs.
For a delegate you should pretty much always use weak. Normally you'd only pick assign if you are dealing with millions of objects. Typically that doesn't happen with delegates.
Which is the best method
Override "release" or "dealloc" method in objective c?
why?
Under non-ARC, 99% of the cases you should not override the release method.
I have seen only 1 case that the need to override the release method - a kind of singleton, which forces the class have really 1 single instance no matter how many times you call alloc.
That way override not only the release method, but also allowWithZone:, retain, 'retainCount`, etc. (It is actually not common to implement that kind of singleton)
Which is the best method? Override the release or the dealloc method?
- dealloc, definitely. You should never override - release.
Why?
One, because release does a bunch of internal stuff. Two, because if release is called, it does not mean that the object is deallocated.
So you would release your ivars or null your properties by accident. And who wants an ugly segfault when we can have worldpeace instead?
If an object is really deallocated, - dealloc will be called.
If you are not using ARC, you should override the -[MyObject dealloc] dealloc method to release all retained objects inside your object. I have never found a case where I needed to override the release method.
If you are using ARC, you can usually avoid overriding the -dealloc method at all, unless you are using anything that ARC won't free up like a sqlite pointer or something.
dont override either for anything not relating to memory management - you dont when and if those methods even get called.
exceptions for when you should dealloc:
removing KVO / notification center observer
deallocating manually allocated memory (arc) / release your ivars (non-arc)
I have this in my .h file:
#property (nonatomic,retain) CCTexture2D *tempScreenshot;
Since it says "retain", I'm assuming that whatever value is stored in tempScreenshot is retained.
Do I have to release tempScreenshot in the dealloc method of my class?
Also, if I use the set method to give a new value to tempScreenshot, this new value will be retained, right? What happens to the old value?
Since you're saying "retain" I am assuming this is manual memory management code. If at all possible, you should switch to automatic reference counting (ARC). It dramatically simplifies this work and is faster than the equivalent manual code. Other than support for older OSes, there is almost never a reason to do manual memory management anymore.
Since it says "retain", I'm assuming that whatever value is stored in tempScreenshot is retained.
Whenever you call [self setTempScreenshot:], the accessor will retain the parameter and release the old value. Assigning the ivar directly will not give you any of this. You should always use the accessor except in init and dealloc.
Do I have to release tempScreenshot in the dealloc method of my class?
Yes.
Also, if I use the set method to give a new value to tempScreenshot, this new value will be retained, right? What happens to the old value?
It will be released as long as you use the accessor.
The retain keyword marks the property as retain upon assignment, meaning that on a set, retain will be called on the new value, and release will be called on the old value.
You will need to release the object on dealloc.
In your dealloc method, do: self.tempScreenshot = nil;
This will cause the object to be released. It will then be deallocated assuming nothing else has retained it.
If you were to write your own setter method to retain an object it would look like this.
//Assume an instance variabled name obj for this example
- (void)setAndRetainObjectExample:(NSObject *)newObj {
[obj release];
obj = newObj;
[obj retain];
}
Using the synthesized methods is much cleaner, but looking at it this way may clear up any confusion.
I'm declaring an ivar of type NSString on a class. To initialize the value of this ivar I use the following code:
NSString *myVar;
-(void)inAnyMethod
{
myVar = [NSString stringWithFormat:#"%#",theValue];
}
Do I have to release this ivar? According to my understanding, it is not my responsibility. But in most cases, strings that I use in this manner cause leaks.
What am I missing?
You do not have to release it, because that is a convenience method that returns an autoreleased object.
The way to know if you are getting something with a retain count of 1 that you will need to release is using the Cocoa naming conventions which say that anything that starts with new, alloc or contains copy in the method name will return a retain 1 object, the others will return autoreleased objects like in this case.
In addition to Oscar Gomez answer, note that when you use class methods (those methods with plus sign that you can find in the documentation and are not included in Oscar Gomez list, e.g. stringWithFormat is one of them), you have not to worry about memory management. If you create your own class method, you should do the same: return an autorelease object.
Regarding your code, it cannot work if you simply assign your ivar to the NSString object (returned from that method). In fact, at some point of your application cycle, the object will be released (it has been put in a pool) and your ivar will not reference any object anymore.
The trick: create a #property with a copy policy or send a copy message like the following:
myVar = [[NSString stringWithFormat:#"%#",theValue] copy];
Copy is normally used when a class has subclasses of mutable type. Otherwise use retain. Once done, you have the possession for that object and you have to remember to release it. If you don't do it you cause a leak.
[myVar release];
P.S. Since Xcode 4.2 there is a new compiler feature called ARC.
Hope it helps.
If we write the following code:
ExplorerAppDelegate * appDelegate = (ExplorerAppDelegate *)[[UIApplication sharedApplication] delegate];
This makes a reference to the original delegate pointer, but:
Does it increase the reference count?
Do we have to explicitly call as [ExplorerAppDelegate retain] right after, or not at all?
What's happening, exactly?
After we've used this, we should also do a [ExplorerAppDelegate release] in the dealloc method, right?
No, it does not increase the retain count.
The convention in Objective-C is that objects you are given should be memory managed by yourself - but in the case of obtaining a shared common resource like the app delegate, the memory is maintained elsewhere and of course (with this being the app delegate) you know that it will always be "alive" as long as your class is... so there is no need to retain the reference.
In most uses of delegates, instead of fetching a delegate you are given one, and that reference is not retained either. In that case whoever gave you the delegate is also responsive for clearing out the delegate link before the delegate is released.
The reason you don't want to generally retain delegate references is that it can prevent some objects from being deallocated, for instance if one class is a delegate of a class that ues the other class as a delegate.
The reference count will not be increased
You should retain it if you want to be sure that it isn't deallocated while you have a pointer to it
You should only release it if you retained it
So basically, if you're only using the object in a single function, you probably don't need retain or release it. If it exists when you get it, then it's (probably) not going to be deallocated by the end of the function. If you're keeping it around, in an ivar (member variable) for example, then you should retain it and release it later.
See the "Weak References to Objects" in Memory Management Programming Guide for Cocoa for the official answer. Pointers to delegates are one of the possible exception cases to the memory management rules.