Objective-C, ownership and class methods - objective-c

First off, I'm a Objective-C newbie. :)
I've learned that anything that starts with alloc, new, and copy, gives the caller ownership of the returned object. Does this also apply to class methods? I'm guessing it does, and a recent crash in one of my unit tests seems to confirm it. Apple's Advanced Memory Management Programming Guide doesn't say anything whether there's a difference between class and instance methods.
Update
What I mean that it also applies to class methods is really the "inverse". For instance, NSDecimalNumber has a class method called +decimalNumberWithDecimal:. It seems to return an auto released object (if I release it explicitly, a crash occurs shortly after that). In hindsight, the answer to my question is obvious, as Apple's guide refers to new and alloc as ownership-giving methods, and they're all class methods. Sorry for taking up your valuable time. :)

Also alloc and release. init does not indicate ownership, you are likely mixing that up with alloc. You can memorise it easily with the mnemonic NARC.
If you are naming any class methods init, copy or retain, you should stop that. Those are methods that only make sense in the context of instances. alloc and new are class methods and should only be used in that context. Don't name instance methods alloc or new.
The reason why the guide doesn't say that it applies to both instance methods and class methods is that the methods in question are clearly a mixture of both, so it's obviously the case.

Yes this applies to class methods since alloc and new are class methods which return ownership to the caller. The prefix of copy or mutableCopy should be used for instance methods returning ownership.
Edit For The Update:
You are correct a method like +decimalNumberWithDecimal: is expected to return an autoreleased object, therefore there is no reason to release it. If however they decided to name the method +newNumberWithDecimal: then you would have ownership of the returned object and need to release it. Clang static analyzer will actually complain if you prefix a method with new and return an autoreleased object.

Actually, this is almost correct. alloc, new, and copy give you ownership of the returned object. These are class methods. Other class methods should return an autoreleased object. Instance methods should also return an autoreleased object.
init does not effect ownership and should be use in conjunction with alloc as follows.
[[SomeCoolClass alloc] init]
new is usually the same thing as the above and is sometimes described as "almost deprecated" because it is a throwback to the NeXT days when the allocation and initialization were done in the same step and could not be plot apart as we do today with alloc and init.
Release does not effect ownership, but should only be used on object you already own. Otherwise a crash is likely to occur.
Retain also does not affect ownership, but should only be used on an object you already own. Otherwise the object may not be deallocated when it should be. The result could be a crash, but it can also be very very strange behavior that is difficult to troubleshoot because messages may be sent to the original object that was supposed to have been deallocated instead of a new object pointed to at the same address.

Related

release for objects on Class method?

Without using ARC, for objects initialized using instance method we do release it via release call.
example:
Sample *obj = [[Sample alloc]init] ;
// some code here
[obj release] ;
Now for objects allocated using class methods should release be called?
example:
TestSample *testobj = [TestSample initCustom] ;
// some code here
should there be [testobj release]?
Let's consider this standard function provided by apple.
endpointWithHostname is a class method.
NWHostEndpoint *pNetHost = [NWHostEndpoint endpointWithHostname:#"0.0.0.0" port:#"21"];
so, should there be a [pNetHost release] for above call?
You said:
for objects initialized using instance method we do release it via release call
The fact that you called an instance method isn’t relevant. You own any object returned by any method whose name starts with alloc, new, copy, or mutableCopy. In your example, you called alloc, and therefore ownership has been transferred to you. That’s why you are now responsible for calling release.
However, if you called some instance method that didn’t start with one of those four prefixes, though, ownership would not be transferred to you, and you would not call release.
This is all summarized in the Advance Memory Management Programming Guide, which says:
Basic Memory Management Rules
The memory management model is based on object ownership. Any object may have one or more owners. As long as an object has at least one owner, it continues to exist. If an object has no owners, the runtime system destroys it automatically. To make sure it is clear when you own an object and when you do not, Cocoa sets the following policy:
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
You can take ownership of an object using retain
A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. You use retain in two situations: (1) In the implementation of an accessor method or an init method, to take ownership of an object you want to store as a property value; and (2) To prevent an object from being invalidated as a side-effect of some other operation (as explained in Avoid Causing Deallocation of Objects You’re Using).
When you no longer need it, you must relinquish ownership of an object you own
You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object.
You must not relinquish ownership of an object you do not own
This is just corollary of the previous policy rules, stated explicitly.
You go on to ask:
let's consider this standard function provided by apple. endpointWithHostname is a class method.
NWHostEndpoint *pNetHost = [NWHostEndpoint endpointWithHostname:#"0.0.0.0" port:#"21"];
so should there be a [pNetHost release] ; for above call
The fact that it is a class method isn’t relevant. The key is that the method name doesn’t start with alloc, new, copy, or mutableCopy. That means that ownership has not been transferred to you and therefore you don’t need to call release. In this case, it is returning an autorelease object, so it will be released for you when the autoreleasepool is drained.
Obviously, if you want to claim ownership of the pNetHost object, you would do so by calling retain (and of course, at that point you’d then be responsible for eventually calling release to offset that retain).
Now, let’s consider your example:
TestSample *testobj = [TestSample initCustom];
// some code here
should there be [testobj release]?
No. But let’s answer this question by looking at the implementation of the method you called initCustom. It might be implemented like so:
+ (instancetype)testSample {
TestSample *obj = [[self alloc] init];
// perhaps more customization of `obj` here
return [obj autorelease];
}
But, there are two key observations in the above:
I didn’t start the method name with init. That prefix should only be used with initialization methods, which this method isn’t.
The convention is to start the method name with the name of the object type, using camelCase (i.e. starting with a lowercase letter). Hence, this TestSample class method name might be called testSample, like above, not initCustom.
Because the method name doesn’t start with alloc, new, copy, or mutableCopy, it should return an autorelease object. And because it is an autorelease object, the caller would therefore would not call release (unless, of course, it claimed ownership by calling retain).
By the way, the static analyzer (shift+command+B; or “Product” » “Analyze”) is exceptionally good at analyzing manual reference counting code.
For example, let’s imagine that I forgot to add the autorelease in the above testSample example. If I let Xcode analyze the code, the compiler would tell me about the problem:
If I add the autorelease back in and re-analyze, this warning will go away.
When writing manual reference counting code, the static analyzer is an invaluable tool. Always make sure you have a clean bill of health from the analyzer.

Conflict between memory management descriptions in ObjC book and official docs

I'm trying to learn/understand what happens and why when working with or creating various objects. (Hopefully to LEARN from the docs.)
I'm reading "Programming in Objective-C 2.0" (2nd edition, by Steven Kochan). On page 408, in the first paragraph is a discussion of retain counts:
Note that its reference count then goes to 2. The addObject: method does this automatically; if you check your documentation for the addObject: method, you will see this fact described there.
So I read the addObject: docs:
Inserts a given object at the end of the array.
There, the description is missing, while other items, like arrayByAddingObject:, state it:
Returns a new array that is a copy of the receiving array with a given object added to the end.
Where in the reference does it indicate that addObject: increases the retain count? Given the presence of ARC, I should still understand what these methods are doing to avoid bugs and issues. What does ARC bring to this? (Going to read that again...)
Great question, I'm glad to see someone actually reading the docs and trying to understand them!
Since you are looking for how to research answers using Apple's documentation more so than the actual answer itself, here is how I found the answer:
First I look at the class reference for addObject: which is a method of NSMutableArray and there is no mention of memory management.
Then I look at the Overview section at the top... Hmmm, still no luck.
Since the behavior might be inherited from a parent class, I look at the Inherits from section at the top of the class reference and see that NSArray is the most immediate parent. Let's check there:
Under the Overview There is one small section about retain's:
Special Considerations
In most cases your custom NSArray class should conform to Cocoa’s
object-ownership conventions. Thus you must send retain to each object
that you add to your collection and release to each object that you
remove from the collection. Of course, if the reason for subclassing
NSArray is to implement object-retention behavior different from the
norm (for example, a non-retaining array), then you can ignore this
requirement.
Okay, I'm still not happy... Where next? The parent class of NSArray is NSObject and I know that it won't be covered there in this case (from experience) so I won't bother checking that. (If the parent was another class or something that might be covered by NSObject, I would keep moving up the tree until I found something.)
The Companion Guides usually contains a lot of good information for these types of classes. Let's try the first one, Collections Programming Topics.
The first section (after Overview) is Accessing Indexes and Easily Enumerating Elements: Arrays. Sounds promising! Click on Relevant Chapters: “Arrays: Ordered Collections”
There it is under Array Fundamentals along with a link to even more information:
And when you add an object to an NSMutableArray object, the object
isn’t copied, (unless you pass YES as the argument to
initWithArray:copyItems:). Rather, an object is added directly to an
array. In a managed memory environment, an object receives a retain
message when it’s added; in a garbage collected environment, it is
strongly referenced. When an array is deallocated in a managed memory
environment, each element is sent a release message. For more
information on copying and memory management, see “Copying
Collections.”
The book must be referring to out of date documentation because you are correct it doesn't mention anything about the retain count. It does in fact retain the object though. The way you need to think of it is not in terms of retain counts (which are useless) but rather ownership. Especially so when using ARC.
When you add an object to an NSMutableArray, it is taking ownership of that object (in ARC terminology it has a strong reference to it).
"What does ARC bring to this?"
ARC does nothing different. All ARC does (besides some optimization) is add the same release, retain, and autorelease statements that you would add yourself without using ARC. All you need to care about is that once you add an object to the array, it will live at least as long as the array.
And the arrayByAddingObject: method creates a new NSArray (or NSMutableArray) containing the object you're passing, and keeps a strong reference to the passed object. The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan.
Basically even without ARC, it's best to think of object life-cycles in terms of ownership, ARC just formalizes that. So because of that, when using the frameworks, it doesn't matter when retains happen or don't happen, you are only responsible for your objects until you pass ownership to another object and you can trust that the framework will keep the object alive as long as it needs it.
Now of course you have to intuit what constitutes ownership. For instance delegate properties are often assign, or in ARC unsafe_unretained or weak, to prevent circular retains cycles (where two objects each retain each other), though are sometimes retained/strong so you need to look into those on a case by case basis.
And also in cases like key value observing and NSNotification observing the object you are observing does not retain the observer.
But those are really exceptions to the rule. Generally you can assume a strong reference.
Regarding this sentence above: "The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan." I'll try to explain:
When you run this piece of code: [someArray arrayByAddingObject:someObject]; you've instantiated a new NSArray or NSMutableArray object (depending on which object type someArray is) but you haven't actually assigned it to any reference. That means that if you're using ARC, it may be immediately released afterwards, or if not using ARC, it will be released when it's autoreleasepool is drained (probably on the next iteration of that thread's runloop).
Now if instead you did this: NSArray *someOtherArray = [someArray arrayByAddingObject:someObject]; you now have a reference to the newly created array, called someOtherArray. In this case, this is a local variable who's scope is only within whichever set of { } it resides (so it could be inside an if statement, a loop, or a method. Now if you do nothing else with it, it will die sometime after it's scope ends (it isn't guaranteed to die right away, but that isn't important, you just can't assume it lives longer).
Now if in your class you have an iVar (instance variable) declared in the header like NSArray *someOtherArray; (which is strong by default in ARC) and you run someOtherArray = [someArray arrayByAddingObject:someObject]; somewhere in your class, the object will live until you either remove the reference (someOtherArray = nil), you overwrite the reference (someOtherArray = someThirdArray), or the class is deallocated. If you were not using ARC, you would have to make sure to retain that to achieve the same effect (someOtherArray = [[someArray arrayByAddingObject:someObject] retain]; which is essentially what ARC is doing behind the scenes).
Or you may have a property declared instead like #property (nonatomic, strong) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would achieve the same effect but would use the proprety accessor (setSomeOtherArray:) or you could still use someOtherArray = [someArray arrayByAddingObject:someObject]; to set the iVar directly (assuming you #synthesized it).
Or assuming non-ARC, you might have declared the property like #property (nonatomic, retain) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would behave exactly as ARC would, but when setting the iVar directly you would still need to add that retain manually.
I hope that clears things up a bit, please let me know if there's anything I glossed over or left out.
As you mentioned in your comment, the key here is intuitively knowing when an object would be considered owned by another one or not. Luckily, the Cocoa frameworks follow a pretty strict set of conventions that allow you to make safe assumptions:
When setting an NSString property of a framework object (say the text property of a UILabel for example) it is always copied (if anyone knows of a counter-example, please comment or edit). So you don't have to worry about your string once you pass it. Strings are copied to prevent a mutable string from being changed after it's passed.
When setting any other property other than delegate, it's (almost?) always retained (or strong reference in ARC)
When setting delegate properties, it's (almost?) always an assign (or weak reference) to prevent circular retain cycles. (For instance, object a has a property b that is strong referenced and b has a strong referenced delegate property. You set a as the delegate for b. Now a and b are both strongly referencing each other, and neither object will ever reach a retain count of 0 and will never reach it's dealloc method to dealloc the other object. NSURLConnection is a counter-example that does strongly reference it's delegate, because it's delegate is set via a method -- see that convention below -- and it's convention to nil out or release an NSURLConnection after it completes rather than in dealloc, which will remove the circular retain)
When adding to an array or dictionary, it's always retained (or strong reference).
When calling a method and passing block(s), they are always copied to move them from the stack (where they are initially created for performance purposes) into the heap.
Methods that take in object parameters and don't return a result immediately are (always? I can't think of any that don't) either copying or retaining (strong referencing) the parameters that you pass to ensure that the method can do what it needs to with them. For instance, NSURLConnection even retains it's delegate because it's passed in via a method, whereas when setting the delegate property of other objects will not retain, as that is the convention.
It's suggested that you follow these same conventions in your own classes as well for consistency.
Also, don't forget that the headers of all classes are available to you, so you can easily see whether a property is retain or assign (or strong or weak). You can't check what methods do with their parameters, but there's no need because of the convention that parameters are owned by the receiver.
In general, you should look in the "most global" spot for information about anything in the Cocoa APIs. Since memory management is pervasive across the system APIs and the APIs are consistent in their implementation of the Cocoa memory management policy, you simply need to read and understand the Cocoa memory management guide.
Once understood, you can safely assume that all system APIs implement to that memory management policy unless explicitly documented otherwise.
Thus, for NSMutableArray's addObject: method, it would have to retain the object added to the array or else it would be in violation of that standard policy.
You'll see this throughout the documentation. This prevents every method's documentation from being a page or more long and it makes it obvious when the rare method or class implements something that is, for whatever reason (sometimes not so good), an exception to the rule.
In the "Basic Memory Management Rules" section of the memory management guide:
You can take ownership of an object using retain.
A received object is normally guaranteed to remain valid within the
method it was received in, and that method may also safely return the
object to its invoker. You use retain in two situations: (1) In the
implementation of an accessor method or an init method, to take
ownership of an object you want to store as a property value; and (2)
To prevent an object from being invalidated as a side-effect of some
other operation (as explained in “Avoid Causing Deallocation of
Objects You’re Using”).
(2) is the key; an NS{Mutable}Array must retain any added object(s) exactly because it needs to prevent the added object(s) from being invalidated due to some side-effect. To not do so would be divergent from the above rule and, thus, would be explicitly documented.

What happens when alloc or allocWithZone is called?

I wanted to know , How exactly does an Objective C object gets created. I have been reading different blog posts and apple docs but I could only find incomplete information here and there about ivar and objc_class structures ad various other runtime methods and structures.
But I still did not get, What happens when we call alloc on a Class and how are superclass data members added to the structure ?
If possible, can any one Explain this to me or point me to the source code of these methods that actually allocate memory ?
When alloc is called, it (as any other message send) first gets transformed (by the compiler) into one of the objc_msgSend* functions. This function will get the class structure pointer as its first argument, and #selector(alloc) as its second.
Then, objc_msgSend looks up the corresponding method implementation of +[class alloc], which is, in general, not overridden (custom initialization is conceptually done in -initWith...), so it will generally be +[NSObject alloc]. It is likely that alloc simply calls +[NSObject allocWithZone:]; that function's implementation might do the following steps:
1) It finds the class' istance size (probably via class_getInstanceSize())
2) It allocates memory, most likely using the class_createInstance() function. This function clears the allocated memory to zeroes (that's why, as the specs say, all your ivars are explicitly initialized to 0 on startup), then sets the newliy created object's isa pointer to the class structure itself.
3) The allocWithZone: methods returns the fresh object pointer to alloc
4) alloc returns the object pointer to the sender, most likely it will run into [Class initWith...:].
Hope this helps. Also, apart from the Obj-C runtime docs, don't forget to check the GNUstep NSObject implementations. That's a logic and possible way how the GNU people implemented it and how Apple might have implemented it.
Check out http://www.mikeash.com/pyblog/friday-qa-2009-03-13-intro-to-the-objective-c-runtime.html

Why does a Convencience Constructor or Object Factory have to care about releasing the Object?

Actually, if you use a method with "new", "create", "alloc" or "copy" in it's name, then you are responsible for releasing the object that is returned to you. BUT: Why do these methods make an call to -autorelease? Wouldn't this result in "over-releasing" the object?
Lets say I get that object from such a method, and then I call -release on that. The object is in the Autorelease Pool and has a reference count of 0. What would happen next, when the Autorelease Pool is released?
Convenience constructors don't have any of those words in their names (e.g., [NSMutableArray array]), so by convention they return autoreleased objects. Methods that do have one of the words that indicate they return a retained object don't call autorelease, so that part of the premise of your question is incorrect.
If you release objects returned from a convenience constructor yourself (without having explicitly retained them) then they will be over-released, and your application will probably crash.
Sorry #all! I've been sitting too long in the bright sun, I think. Of course these convenience methods have ownership of the objects they create, because they call -alloc at some point at the beginning. And the -alloc Method itself doesn't call -alloc, since it's -alloc already. That's it.
Thought about deleting the question, but maybe someone else was sitting in the sun for too long, too, just like me. So this might help.

How to know if an object is autoreleased or not?

I'm getting a a bit annoyed about some objects being autoreleased without me knowing. It's probably a good thing that they are, but if they are, I want to know. The documentation doesn't say which methods autorelease objects, so I usually test my way forward, which in my opinion is silly. For example, [NSDate date] autoreleases the object, and so does [NSArray arrayWithObjects:...]. How do you know without the documentation telling you?
I'm starting to see a pattern though that methods like these, the ones that create objects with a static function, always returns the autoreleased object. Is this always true?
Basically, if you init, copy, or retain an object you are responsible for releasing it. If you don't, you are not responsible for releasing it.
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Many classes provide methods of the
form +className... that you can use to
obtain a new instance of the class.
Often referred to as “convenience
constructors”, these methods create a
new instance of the class, initialize
it, and return it for you to use.
Although you might think you are
responsible for releasing objects
created in this manner, that is not
the case according to the ownership
policy set out earlier. Because the
class creates the new object, it is
responsible for disposing of the new
object.
The method signature itself tells you. The pattern to methods with signatures like "classNameWithData:data1:data2" is to return an alloc/init/autorelease instance of that thing. They are conveniences there so that you don't have to do it.
If you do not want an autorelease version of something, then do not instantiate them that way, and use the proper alloc/init, and release when you are done. This method is much more explicit, and a bit more error prone because if an exception is thrown your release block could get missed, but that is the price you pay for having it that way.