release for objects on Class method? - objective-c

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.

Related

Need to release twice?

I can't seem to find the answer anywhere. I'm using Manual Memory Management in Objective-C developing for iOS.
I wrote a convenience function for getting UIColor from a hex string. In it, it returns
[[UIColor alloc] initWithRed:... alpha:alpha]
Apparently on certain platforms (we have a few devices, ranging iOS 8-9) the object would be destroyed on exiting the function, so that its returned UIColor* cannot be used. So now, we changed it to
[[[UIColor alloc] initWithRed:... alpha:alpha] retain]
My question is when I'm done using this object, do I have to release it twice? Once for the alloc, once for the retain? It seems very strange to me, and I can't find this online anywhere.
If I don't retain, it gets dealloc'd on exiting the function (on some platforms) making the function useless. If I do retain, I need to release twice when done?
EDIT:
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html
"..., it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. "
So I'm not doing anything out of the ordinary. The docs say I "should retain it" if "I want it to remain valid beyond" the scope of a function. I will try what #FreeNickname suggested. That makes the most sense.
You said:
I wrote a convenience function for getting UIColor from a hex string. In it, it returns
[[UIColor alloc] initWithRed:... alpha:alpha]
According to the Basic Memory Management Rules, the proper memory management is dictated by the name of your method:
if your method name does not start with “alloc”, “new”, “copy”, or “mutableCopy”, then you should return an autorelease object:
- (UIColor *)colorWithHexString:(NSString *)hexString {
...
return [[[UIColor alloc] initWithRed:... alpha:alpha] autorelease];
}
if your method name does start with “alloc”, “new”, “copy”, or “mutableCopy”, then you can return an object like you have above:
- (UIColor *)newColorWithHexString:(NSString *)hexString {
...
return [[UIColor alloc] initWithRed:... alpha:alpha];
}
Note, this pattern is less common than the above convention of colorWithHexString.
(Note, this memory management dictated by the method name prefix was historically merely best practice, but now, for interoperability with ARC code, it's critical. Always follow the above rules in manual reference counting code.)
Now, if the code that is calling your convenience initializer is allowing the object to be deallocated, the problem rests with that code, not your convenience initializer. Do not start adding extra retain statements to your initializer because something that calls it doesn't manage its memory properly.
Instead, make sure that the calling code does the proper retain (and eventual release) of the result of colorWithHexString, itself.
By the way, Xcode's static analyzer (shift+command+B) is remarkably good at analyzing manual reference counting code and identifying the issues.
In an edit to your question, you quoted the documentation:
If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. If you try to release an object that has already been deallocated, your program crashes.
This is not saying that your convenience initializer should issue a retain or copy. It is saying that the code that calls colorWithHexString is responsible for establishing its own claim of ownership of the UIColor object that was returned via retain or copy, as discussed above.
I think you are looking for the concept of autorelease which is used in situations like yours. It is essentially a way to send a deferred release message to the newly created object so the caller has the chance to retain it if necessary, otherwise it is destroyed when the autoreleasepool is processed.
You "misunderstood" Apple's documentation, because it is simply wrong for this topic. You really should read clang's documentation about ARC instead of Apple's, because clang's ARC documentation explains MRC correctly to interact with it.
Let's have a closer look on it:
You own any object you create by allocating memory for it or copying it.
Related methods: alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:
…
Conversely, if you are not the creator of an object and have not expressed an ownership interest, you must not release it.
…
If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in.
Taking this documentation for serious, you are not an owner of the object:
[[UIColor alloc] initWithRed:... alpha:alpha]
This is, because you do not receive the object reference from +alloc et al., but from -init…. Following Apple's documentation you are not an owner and have to retain it. (So it is "elsewhere".)
In clang's documentation it is described differently and correctly:
Methods in the init family implicitly consume their self parameter and return a retained object. (5.2.1)
Therefore there is a special method family for -init… along with the others mentioned in Apple's documentation as correctly described in clang's documentation:
The families and their added restrictions are:
alloc methods must return a retainable object pointer type. [Apple: alloc, allocWithZone:)
copy methods must return a retainable object pointer type. [Apple: copy, copyWithZone:)
mutableCopy methods must return a retainable object pointer type.(Apple: mutableCopy, mutableCopyWithZone:)
new methods must return a retainable object pointer type. (Apple: Ooops, I forgot something)
init methods must be instance methods and must return an Objective-C pointer type. … (Apple: Oooops, I forgot something)
(5.)
So, what you get from -init is already retained, you have the ownership and there is definitely no reason to retain it.
According to Rob's answer there might be a reason to autorelease it.

Objective-C, ownership and class methods

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.

using alloc and init

We know about the complete pattern of alloc/init that alloc and init must be combined.
NSObject *myObj = [[NSObject alloc] init];
1- init method receives the object from another source(not from a alloc,new,copy or alike or retained) so according to the fundamental memory management rule its not the owner and it must not release it. However, "Allocating and Initializing Objects / The Returned Object" article says that init could free the receiver.
How could this be possible when its against the fundamental rule?
2- Also, from the same article, init could return another object or nil. So, in this case, when we use the complete pattern of alloc/init, we could not release the object returned by alloc but we could only release the object returned from init and, init releases the object it received from alloc instead of us.
But init is not a alloc,new,copy or alike method so we must not release the object returned from it as it does not give us the ownership of object.
How could we release the object returned from init although this is against the fundamental rule?
3- Or, to adhere to the last paragraph of the same article, must we accept init method as a special case and use alloc/init pattern as an exception to the fundamental rule?
Memory Management Fundamental Rule:
You only release or autorelease objects you own.
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message.
You use release or autorelease to relinquish ownership of an object. autorelease just means “send a release message in the future” (to understand when this will be, see “Autorelease Pools”).
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
Allocating and Initializing Objects / The Returned Object:
However, in some cases, this responsibility can mean returning a different object than the receiver. For example, if a class keeps a list of named objects, it might provide an initWithName: method to initialize new instances. If there can be no more than one object per name, initWithName: might refuse to assign the same name to two objects. When asked to assign a new instance a name that’s already being used by another object, it might free the newly allocated instance and return the other object—thus ensuring the uniqueness of the name while at the same time providing what was asked for, an instance with the requested name.
In a few cases, it might be impossible for an init... method to do what it’s asked to do. For example, an initFromFile: method might get the data it needs from a file passed as an argument. If the file name it’s passed doesn’t correspond to an actual file, it won’t be able to complete the initialization. In such a case, the init... method could free the receiver and return nil, indicating that the requested object can’t be created.
Because an init... method might return an object other than the newly allocated receiver, or even return nil, it’s important that programs use the value returned by the initialization method, not just that returned by alloc or allocWithZone:. The following code is very dangerous, since it ignores the return of init.
id anObject = [SomeClass alloc];
[anObject init];
[anObject someOtherMessage];
Instead, to safely initialize an object, you should combine allocation and initialization messages in one line of code.
id anObject = [[SomeClass alloc] init];
[anObject someOtherMessage];
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocAllocInit.html
The init method doesn't receive the object; the object receives the init message. The object does not possess itself; rather, it always knows about itself (through the implicit self argument in every message).
You're right that the object does not own itself, though. If alloc and init were fused in a single new method, that method would be its own (super) caller, so it would own the object (until it returns) and so be unquestionably right in releasing it. Since they are separate, and init is not the caller of alloc, you're right that it does not own the object, so you are right to question this practice.
This is one of the few cases where it's OK for one object to release an object (in this case, itself) on behalf of another. The alternative is not to release it, which, if you're going to either return nil or throw an exception, will be a leak.
In general, anytime you have an object retain or release itself, you should feel dirty. In this specific case, it's OK, because you are preventing a bug (a leak) rather than probably creating one.
2- Also, from the same article, init could return another object or nil. So, in this case, when we use the complete pattern of alloc/init, we could not release the object returned by alloc but we could only release the object returned from init and, init releases the object it received from alloc instead of us.
But init is not a alloc,new,copy or alike method so we must not release the object returned from it as it does not give us the ownership of object.
As init releases the old object on behalf of its caller, if it creates a new object, it does that on behalf of its caller. The caller does own the substitute object that init creates or retrieves for it.
As a corollary to this, if init retrieves a previously existing object, it must retain that, so that the caller will own it.
Again examining the hypothetical* new method, it would also need to both release the old object and create (owningly) or retain the substitute.
In all of these cases, it's init acting on behalf of its caller. It's normally dodgy for one method to do another's memory management, but for these cases, init doing it on behalf of its caller is necessary.
*The new method does exist, but simply sends alloc and init, so there's no need to implement it separately.
If initialization fails for some reason and must return null, then you must release the object in order to avoid leaking memory.
Similarly, init may decide to swap in a different object and return it - in that case you must also release the object in order to avoid leaking memory.
In both cases it's necessary because the original object isn't being returned by init, and will be orphaned after the method returns. Alloc has automatically retained the object, so if you don't release it its retain count will be stuck at 1 forever.
[Would another perspective help?]
The init method (and its siblings initWith... and similar) is a bit of an odd case but is not a special case of memory allocation rules. Init is odd because it has a name that sounds like it is going to change the internals of the instance but in fact it may do more than that (it may substitute some other object and initialize that object, for example). The tip-off is in the declaration of init:
- (id) init // the way it is
vs
- (void) init // in some other universe
The init method returns an object, so it might have been better named something like 'return an object that is (class-wise) an equivalent object and that has been initialized'. Most methods do not perform this kind of switcheroo, which makes init a bit different/odd.
There is nothing 'magic' about the alloc / init nesting -- it's just the simplest way to handle the fact that the object that you get back from alloc may not be the same object you get back from init. This works perfectly fine:
NSSomeClass* s = [NSSomeClass alloc];
s = [s init]; // that 's =' part is really important ;-)
and is exactly equivalent to the 'standard' idiom:
NSSomeClass* s = [[NSSomeClass alloc] init];
This is potentially problematic:
NSSomeClass* s = [NSSomeClass alloc]
[s init]; // bad! you ignored the result of init
The implementation of an init method must be done particularly carefully when the implementation returns a different object than the one it receives as the incoming 'self'. In such a case the init method takes on the responsibility of memory management of the 'self' object (because it's not going to return that object - so who else could be expected to do the management?)
It's possible to do some pretty ugly trickery, BTW. Don't try this at home!
// don't do this!
S* s = [S alloc]
[s retain]; // needs to survive 2 init's
S* ss = [s init......]; // s.retain goes 2-->1
S* sss = [s init.....]; // ... goes 1-->0;
Doing this is extremely poor practice because it depends on the init..... method always returning a new object (instead of the one it receives). That's an obviously bad assumption!
NOTE that by "a method receiving an object in 'self'" I mean that the method was invoked upon/by an object, and that object is made available by convention through the 'self' pointer.
The fundamental rule just doesn't apply in this special situation.
In fact, don't worry about it - unless you plan to do Posing, you won't need to write code that does this, and it will have no impact at all on the code you write.
You should continue to follow the fundamental rule in all your code.
And thirdly, the code is more what you'd call "guidelines" than actual rules.
(Captain Barbosa)
alloc/init is a bit of a special case. You have to do the retain/release stuff inside init in such a way that whatever object the caller gets back is owned by the caller and there are no leaks.

Objective-C Memory Management: When do I [release]?

I am still new to this Memory Management stuff (Garbage Collector took care of everything in Java), but as far as I understand if you allocate memory for an object then you have to release that memory back to the computer as soon as you are finished with your object.
myObject = [Object alloc];
and
[myObject release];
Right now I just have 3 parts in my Objective-C .m file: #Interface, #Implementation and main. I released my object at the end of the program next to these guys:
[pool drain];
return 0;
But what if this program were to be a lot more complicated, would it be okay to release myObject at the end of the program?
I guess a better question would be when do I release an object's allocated memory? How do I know where to place [myObject release];?
This is probably a little over-simplified, but in general, you are going to want to release it where you declared it.
If you declare an object INSIDE a particular method call, then by definition, you will be done with that object (or at least that handle to that object) at the end of that method call... release it then.
If you declare an object as an instance variable, then by definition you will be done with it when that instance is destroyed... release it in the dealloc method of that class.
Keep in mind that "release" does not equal "destroy." When passing objects around in your application, it may make sense to have more than one handle to that object stored in different places... in that case "release" means "I'm done with this object, but someone else may still be using it." Deallocation only occurs when the number of "handles" (retain count) reaches zero.
Apple has some fantastic documentation on memory management, I would check it out at developer.apple.com.
You essentially have three kinds of objects, each with a different pattern.
Transients Objects
In general, you should autorelease transient objects. These are objects that are allocated locally and do not need to exist beyond the method in which they are called. Or they are passed around from method to method.
Chain of Ownership
When one object exists as an instance field inside another, you should release the "owned" (or "child") object when the "owner" (or "parent") object goes out of existence. This is done in the dealloc method of the parent object:
- (void) dealloc {
[child release]; // child was declared as an instance variable
[super dealloc];
}
Lifetime of the Program
When an object is intended to exist for the lifetime of the program, it usually isn't necessary to call release at all, unless some kind of resource cleanup needs to occur. You can put this in applicationWillTerminate:, which you can look up in Apple's documentation.
(You should probably avoid having such objects, but that is a discussion for another question.)
You have to think in terms of ownership. When you take ownership of an object by calling alloc, new or retain, you're also responsible for releasing it, either by calling autorelease when you return an owned object to the caller, or by calling release.
A general rule is:
Local variable: release it within the same method. When you want to return it to the caller, use autorelease
Class member: release it in the dealloc method

How do I handle memory management in this situation?

I have two classes, a class that handles db connectivity and an entity class. The db class has an instance method called GetEntityByID:(int)entity_id. This method does a simple select statement, and creates an Entity class instance using an init method.
This works fine, however whoever calls GetEntityByID must remember to release it. Since GetEntityByID is not an "init" method, this doesn't seem right. How do I best handle memory management in this situation?
You can call autorelease in your GetEntityID method on the class to autorelease the instance if it is not otherwise retained.
Since the instantiation of the class is done within your DB connectivity class's method, the object that is returned the instance does not "own" it - your DB connectivity class. As of this, according to convention, you need to memory manage the instance:
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.
If the object sending the GetEntityID method wants to keep the object around, for example if it is to be used as an instance variable, then the returned object can be retained, preventing it from being deallocated at the end of the current event. If it is only being used locally, and doesn't need to be kept around after the current event, then the class doesn't have to do anything; it will be released by the autorelease pool at the end of the current event.
This article explains more about autorelease pools.
To autorelease the object returned in GetEntityID do something like this in GetEntityID:
... // cool stuff in GetEntityID
return [[entity_id retain] autorelease];
}
Have a look at this really nice article explaining Objective-C memory mangement in more detail.