What is meant by [self release] in Objective-C? [duplicate] - objective-c

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is calling [self release] allowed to control object lifetime?
What will happen if I use this code snippet?
[self release]

self descrements its own retain count by one, just like release would do with any other object.
The only situation however that I have so far come across, where such a call was appropriate, was the case where an init… method would fail and be expected to return nil and deallocate the just allocated instance.
In 9 out of 10 situations you shouldn't use [self release], I'd estimate.
Something like this (which basically forbids the calling of - (id)init;, for cases where you want to force the use of a particular - (id)initWith… method.):
- (id)init {
[self release];
NSString *reason = [NSString stringWithFormat:#"%# is not a valid initializer for the class %#", NSStringFromSelector(_cmd), NSStringFromClass([self class])];
#throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:reason
userInfo:nil];
return nil;
}
or this (which basically enforces the proving of an object on initialization)
- (id)initWithFoo:(Foo *)foo {
if (!foo) {//foo is required to be non-nil!
[self release];
return nil;
}
//proceed with initialization
return self;
}
These however are not the only ever occasions where [self release] would be appropriate. But merely the ones I've come across so far. (as Oliver correctly pointed out)
Edit: Self-invalidating NSTimers would probably be another (quite common, yet somewhat special) situation.

You will release yourself, what means that the object declares itself that it does not have to still live. If no one else retains tha object, it dies and its memory is freed
You have little reasons to do that, except if you want to create object that are not controlled by anyone else and are self controlled.
I mean, for example, there is the case where you may want to create an self living object that makes some treatments, and suicide when it has finished without having to tell anyone else it has finished.
Let's imagine for example a class whose purpose is just to send a message to a server :
You instanciate the class, as soon as it is istanciated it send a message to a server, it waits for the server answer, and if the answer is ok, it suicide. That way, you don't have to manage any server answer from within another class controller whose purpose is not to manage such events.

It just decrements the receiver’s reference count.

Related

Analyzer is complaining about a possible resource leak in multithreaded Cocoa app

Ok, I am an experienced C++ developer. I am learning Objective-C on the fly while trying to build a fairly substantial Cocoa application. I have done some simpler apps with Cocoa while gearing up for this project and I think I have a good handle on most of the concepts.
The memory management paradigm is still a little vague to me however so I build with the memory analyzer to help me find issues right away, and to be honest it has been awesome and has done more to help me understand Objective-C memory management that any of the documentation.
So here is my question.
I have two threads that communicate with each other using the performSelector:onThread:withObject:waitUntilDone: method. They pass objects between each other passed in as the withObject: parameter of the method.
Sample code is below:
- (BOOL)postMessage:(id <MessageTarget>)sender messageId:(NSInteger)msgId messageData:(void*)data
{
// message is allocated and retained here. retain count will be +2
Message* message = [[[Message alloc] initWithSender:sender messageId:msgId messageData:data] retain];
if(message)
{
// message will be released in other thread.
[self performSelectorOnMainThread:#selector(messageHandler:) withObject:message waitUntilDone:NO];
// message is released here and retain count will be +1 or 0 depending on thread ordering
[message release];
return YES;
}
return NO;
}
- (BOOL)sendMessage:(id <MessageTarget>)sender messageId:(NSInteger)msgId messageData:(void*)data messageResult:(void**)result
{
// message is allocated and retained here. retain count will be +2
Message* message = [[[Message alloc] initWithSender:sender messageId:msgId messageData:data] retain];
if(message)
{
// message will be released in other thread. retain count will be +1 on return
[self performSelectorOnMainThread:#selector(messageHandler:) withObject:message waitUntilDone:YES];
if(result)
*result = [message result];
// message is released here and retain count will be 0 triggering deallocation
[message release];
return YES;
}
return NO;
}
- (void)messageHandler:(Message*)message
{
// message will have a retain count of +1 or +2 in here based on thread execution order
if(message)
{
switch ([message messageId])
{
case
...
break;
default:
...
break;
}
// message is released here bringing retain count to +1 or 0 depending on thread execution ordering
[message release];
}
}
The analyzer is complaining about a possible leak of the Message object allocated in postMessage: and sendMessage: but the object is released in messageHandler:. The code runs correctly and does not leak, and I suspect the analyzer is simply not able to see that the Message object is being released in a different thread.
Now in case you are wondering why I do the second retain in the post/send methods and not in the messageHandler: method, it is because the postMessage: method is meant to be asynchronous and [message release] in the post method may get executed before the [message retain] in messageHandler: would, leaving me with an invalid object. It would work just fine if I did that in the case of the sendMessage: method because it is synchronous.
So is there a better way to do this that would satisfy the memory analyzer? Or maybe a way to give the memory analyzer a hint that the object is in fact being released?
Update:
Torrey provided the answer below but I wanted to clarify what I had to do different from what he suggested.
He suggested using an attribute on my messageHandler: method as below
- (void)messageHandler:(Message*) __attribute__((ns_consumed)) message;
This did not quite work since the object is being passed into performSelector: and the analyzer does not see it being passed along to messageHandler:
Since the performSelector: call is defined by Cocoa and not by me I can not add the attribute to it.
The way around this is to wrap the call to performSelector: as follows:
- (void)myPerformSelector:(SEL)sel onThread:(NSThread*)thread withObject:(id) __attribute__((ns_consumed)) message waitUntilDone:(BOOL)wait;
{
[self performSelector:sel onThread:thread withObject:message waitUntilDone:wait];
}
Then you can call the wrapper function and the analyzer will see the attribute and not complain about an unbalanced retain/release pair.
In the end I did not like the extra indirection just to get rid of the warning so I used the preprocessor as explained in my comment below. But I could see situations where it could be useful to use this method.
You do not need to explicitly transfer reference count ops to the secondary thread when using this API.
a) Your caller holds a reference when waitUntilFinished is true,
b) and the implementation behind + [NSThread performSelector:… also does (see: - [NSRunLoop performSelector:target:argument:order:modes:]).
There is no need to pass reference count duties for the parameters (or self) across threads in this case.
It will either be performed immediately, or self and the parameter (it's objc-typed) will be retained while in the other thread's run loop queue (and self and the parameter are released after the object's performed the selector).
(don't use ref-op __attribute__s to shut it up)
You should be able to make the analyzer happy by judicious use of Clang's ns_consumed attribute. As you suggested, this gives the memory analyzer a hint that a release message will be sent to the parameter upon completion of the function call. You would use it like:
- (void)messageHandler:(Message*) __attribute__((ns_consumed)) message
There is more information on Cocoa memory management annotations in the Clang analyzer documentation. You may want to wrap the attribute setting in an NS_COSUMED macro for compatibility with other compilers as suggested on that page.

In objective c can a class essentially delete itself?

In objective c, suppose I have an object Obj stored in a NSMutableArray, and the array's pointer to it is the only strong pointer to Obj in the entire program. Now suppose I call a method on Obj and I run this method in another thread. In this method, if Obj sets the pointer for itself equal to nil will it essentially delete itself? (Because there will be no more strong pointers left) I suspect the answer is no, but why? If this does work, is it bad coding practice (I assume its not good coding, but is it actually bad?)
It is highly unlikely that an object would be in a position to cause its own release/deallocation if your code is designed properly. So yes, the situation you describe is indicative of bad coding practice, and can in fact cause the program to crash. Here is an example:
#interface Widget : NSObject
#property (retain) NSMutableArray *array;
#end
#implementation Widget
#synthesize array;
- (id)init
{
self = [super init];
if(self) {
array = [[NSMutableArray alloc] init];
[array addObject:self];
}
return self;
}
- (void)dealloc
{
NSLog(#"Deallocating!");
[array release];
[super dealloc];
}
- (void)removeSelf
{
NSLog(#"%d", [array count]);
[array removeObject:self];
NSLog(#"%d", [array count]);
}
#end
and then this code is in another class:
Widget *myWidget = [[Widget alloc] init];
[myWidget release]; // WHOOPS!
[myWidget removeSelf];
The second call to NSLog in removeSelf will cause an EXC_BAD_ACCESS due to the fact that array has been deallocated at that point and can't have methods called on it.
There are at least a couple mistakes here. The one that ultimately causes the crash is the fact that whatever class is creating and using the myWidget object releases it before it is finished using it (to call removeSelf). Without this mistake, the code would run fine. However, MyWidget shouldn't have an instance variable that creates a strong reference to itself in the first place, as this creates a retain cycle. If someone tried to release myWidget without first calling removeSelf, nothing would be deallocated and you'd probably have a memory leak.
If your back-pointer is weak (which it should be since a class should never try to own it's owner, you will end up with a retain-cycle) and you remove the strong pointer from the array the object will be removed from the heap. No strong pointers = removed from memory.
You can always test this.
If you need a class to bring to a situation where its deleted, the best practice is to first retain/autorelease it and then make the situation happen. In this case the class won't be deleted in a middle of its method, but only afterwards.
I think we can say it might be bad coding practice, depending on how you do it. There are ways you could arrange to do it safely, or probably safely.
So let's assume we have a global:
NSMutableArray *GlobalStore;
One approach is to remove yourself as your final action:
- (void) someMethod
{
...
[GlobalStore removeObject:self];
}
As this is the final action there should be no future uses of self and all should be well, probably...
Other options include scheduling the removal with a time delay of 0 - which means it will fire next time around the run loop (only works of course if you have a run loop, which in a thread you may not). This should always be safe.
You can also have an object keep a reference to itself, which produces a cycle and so will keep it alive. When its ready to die it can nil out its own reference, if there are no other references and that is a final action (or a scheduled action by another object) then the object is dead.

Block gets released whilst in NSDictionary (ARC)

I'm trying to retain a reference to a Block that's been passed in to my class by a method, to call at a later time. I'm having trouble, however, maintaining a reference to it.
The obvious way, I thought, was to add it to an ivar collection, all of which are supposed to maintain strong references to their contents. But when I try to pull it back out, it's nil.
The code is pretty simple:
typedef void (^DataControllerCallback)(id rslt);
#interface DataController : NSObject {
NSMutableArray* queue;
}
- (void) addBlock:(DataControllerCallback)callback;
- (void) functionToBeCalledLater;
#end
#implementation DataController
- (id) init {
self = [super init];
if (self != nil) {
queue = [NSMutableArray new];
}
return self;
}
- (void) addBlock:(DataControllerCallback)callback {
NSDictionary* toAdd = [NSDictionary dictionaryWithObjectsAndKeys:
[callback copy], #"callback",
#"some other data", #"data", nil];
[queue addObject:toAdd];
}
- (void) functionToBeCalledLater {
NSDictionary* dict = [queue lastObject];
NSLog(#"%#", [dict objectForKey:#"data"]; //works
DataControllerCallback callback = [dict objectForKey:#"callback"]; //this is nil
callback(#"an arguemnt"); //EXC_BAD_ACCESS
}
What's happening?
Update: I've tried it with [callback copy] and just callback inserting into the dictionary, neither works.
Update 2: If I just stick my block into an NSMutableSet, as long as I call copy, I'm fine. It works great. But if it's in an NSDictionary, it doesn't.
I've actually tested it by putting a breakpoint right after the NSDict is created and the callback never gets inserted. The description reads clearly "1 key-value pair", not two.
I'm currently getting around this with a specialised class that just acts as a container. The callback property is declared as strong; I don't even need to use copy.
The question still stands, though: why is this happening? Why won't an NSDictionary store a Block? Does it have something to do with the fact that I'm targeting iOS 4.3 and thus ARC must be built in as a static library?
Update 3: Ladies and gentleman: I am an idiot.
The code I presented here was obviously a simplified version of the actual code; most particularly, it was leaving some key/value pairs out of the dictionary.
If you're storing a value in an NSDictionary using [NSDictionary dictionaryWithObjectsAndKeys:], you had better be damn sure one of those values isn't nil.
One of them was.
ICYMI, it was causing an early termination of the argument list. I had a userInfo-type argument being passed into one of the "add to queue" methods, and you could, of course, pass in "nil". Then when I constructed the dictionary, chucking in that argument caused the constructor to think I had terminated the argument list. #"callback" was the last value in the dictionary constructor and it was never being stored.
Contrary to popular mis-conception, ARC does not automatically de-stackify Blocks passed as arguments to methods. It only de-stackify's automatically when a block is returned from a method/function.
I.e. this....
[dict setObject: ^{;} forKey: #"boom"];
... will crash if dict survives beyond the scope and you attempt to use the block (actually, it won't in this case because that is a static block, but that is a compiler detail that you can't rely on).
This is documented here:
How do blocks work in ARC?
Blocks “just work” when you pass blocks up the stack in ARC mode, such
as in a return. You don’t have to call Block Copy any more. You
still need to use [^{} copy] when passing “down” the stack into
arrayWithObjects: and other methods that do a retain.
The return value behavior could be automated because it is always correct to return a heap based block (and always an error to return a stack based block). In the case of a block-as-an-argument, it is impossible to automate the behavior in a way that would be both very efficient and always correct.
The analyzer likely should have warned about this use. If it didn't, file a bug.
(I derped a stack when I meant a heap. Sorry about that.)
The compiler doesn't automate blocks-as-parameters for a few reasons:
unnecessarily copying a block to the heap can be a significant performance penalty
multiple-copies of a block can multiply that performance penalty significantly.
I.e.:
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
If that were to imply four Block_copy() operations and aBlock contained a significant quantity of captured state, that'd be a huge potential hit.
• There are only so many hours in the day and automating the handling of parameters is rife with non-obvious edge cases. If this were handled automatically in the future, it could be done without breaking existing code and, thus, maybe it will be done in the future.
I.e. the compiler could generate:
aBlock = [aBlock copy];
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
[aBlock release];
Not only would this fix the problem of a block-as-param, but it would also only produce one copy of the block across all potential uses.
The question still stands, though: why is this happening? Why won't an
NSDictionary store a Block? Does it have something to do with the fact
that I'm targeting iOS 4.3 and thus ARC must be built in as a static
library?
Something bizarre is going on, then. Coincidentally, I've been using blocks-as-values in an ARC based application in the last week and it is working fine.
Do you have a minimal example handy?

Reusing NSObjects by Overriding release in Obj-C

I am implementing an object reuse scheme using a singleton class.
What I do basically is:
MyClass* obj = [[MyClassBank sharedBank] getReusableItem];
The bank is just an NSMutableSet tweaked for optimum reusability. When I was happily implementing this Singleton, I had in mind that I will just do the following when I am done with "obj":
[[MyClassBank sharedBank] doneWithItem:obj];
Currently, My code would work if I where to use it this way, but I later realized that I sometimes add "obj" to an "NSCollection", and sometimes I call:
[theCollection removeAllObjects];
At first I thought about making my own class that is composed of a collection, then I would iterate the objects within the collection and call:
[[MyClassBank sharedBank] doneWithItem:obj];
But, that's too much of a hassle, isn't?
A neat idea (I think) popped into my mind, which is to override: -(oneway void)release;, so, I immediately jumped to Apple's documentation, but got stuck with the following:
You would only implement this method to define your own reference-counting scheme. Such implementations should not invoke the inherited method; that is, they should not include a release message to super.
Ao, I was reluctant to do that idea .. basically:
-(oneway void)release{
if ([self retainCount] == 1) {
//This will increment retain count by adding self to the collection.
[[MyClassBank sharedBank] doneWithItem:self];
}
[super release];
}
Is it safe to do that?
PS: Sorry for the long post, I want the whole idea to be clear..
EDIT:
How about overriding alloc alltogther and adding [[MyClassBank sharedBank] getReusableItem]; there?
Suggested method:
You're playing with the reference counting system. 99.9999999999999999% of the time this is a bad idea. I would highly recommend going with a different mechanism. Perhaps these objects could implement their own reference count that's independent of the retainCount? Then you could use that referenceCount to actually control when an object is ready to be re-used or not.
Not suggested method:
If, for some weird reason, you can't do that, then you could do the following thing that is still a bad idea and that i don't recommend you actually use:
You can override dealloc:
- (void)dealloc {
[ivar release], ivar = nil;
[anotherIvar release], anotherIvar = nil;
somePrimitive = 0;
// do not call [super dealloc]
}
- (void)_reallyDealloc {
[self dealloc]; // clean up any ivars declared at this level
[super dealloc]; // then continue on up the chain
}
Basically, the dealloc method would be the point at which the object is ready for re-use. When you're totally done with the object and finally want it to go away, you can use the _reallyDealloc method to continue on up the chain, eventually resulting in the object getting freed.
PLEASE don't do this. With things like Automatic Reference Counting, this is going to introduce you into a world of hurt and really bizarre debugging scenarios. A lot of the tools and classes and stuff depend on the reference counting mechanism to be working without alteration, so screwing around with it is usually not a Good Idea™.
For ppl who find this approach interesting/useful, Here is a cleaner way than calling [super dealloc]; directly (which is definitely bad)
//BAD!
//-(void)dealloc{
// for some reason, the retainCount at this point == 1
// if (![[BankStep sharedBank] purgeFlag]) {
// [self resetObject];
// [[BankStep sharedBank] doneWithItem:self];
// } else {
// [children release];
// [super dealloc];
// }
//}
by calling [[Bank sharedBank] purgeBank]; , set the flag to true, then remove all objects from the NSSet.
Adapted solution:
#Joe Osborn idea of using categories to implement a returnToBank Method!

Calling super in the implementation of an Objective-C block

Is calling a method on super supported in the implementation of an Objective-C block?
When I was calling a method on super an EXC_BAD_ACCESS error would be thrown but as soon as I changed those calls from [super methodToCall] to [self methodToCall] and let the message move up the responder chain it worked fine.
There is no implementation of -methodToCall in the instance of the class that the block exists in, but there is one in the superclass (that is, the class that self inherits from).
I'm just curious to learn the details as to why calling a method on super inside the implementation of a block was a problem in the first place (technically) so I can avoid it in the future. I have a suspicion it is related to how the variables are captured in the block and something about the stack and the heap, but I really have no concrete idea.
Note: the block implementation code is called up to a few seconds after the block is stored in a property, the property uses copy so I don't think it's a problem with the block's lifecycle, that all looks to be fine. Also, this was only crashing on the iPhone device (3G) but was working without crashing in the iPhone Simulator.
Results in EXC_BAD_ACCESS:
[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
if (!error) {
[super didRetrieveItems];
} else {
[super errorRetrievingItems];
}
}];
Works perfect, implementations of -didRetrieveItems and -errorRetrievingItems are in the super-class.
[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
if (!error) {
[self didRetrieveItems];
} else {
[self errorRetrievingItems];
}
}];
Technically, this is an issue with the Objective-C runtime, and the underlying mechanics of how calls to super actually work. Basically, they capture both the object which is the recipient of the message (self in all cases) and the class which implements the specific version of the method (the superclass of the class in which the method implementation occurs). Because a lot of the preparation for such a message send happens at compile-time, not runtime, I wouldn't be surprised if it interacted badly with blocks.
I would check to see if self is still valid when the message is about to be sent. Normally, any objects referenced in a block are automatically retained. Since super works a bit differently, it might mean that self is not getting retained like one would expect. One easy way to check this would be to use the calls to super as originally written, and simply leak the object referred to as self, and see if it works. If this turns out to be the problem, you might have to insert a dummy reference to self within the block to get that automatic memory management.
In the strictest sense, however, I'm not sure you can depend on this working forever and always. Although blocks can capture the current runtime state, it doesn't really make sense (from an OOP perspective) for them to break encapsulation and invoke superclass implementations, since the hierarchical level at which methods are implemented should be opaque to any external calling code. I would try to find another solution which doesn't depend on the inheritance hierarchy.
Results in EXC_BAD_ACCESS:
[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
if (!error) {
[super didRetrieveItems];
} else {
[super errorRetrievingItems];
}
}];
Probably due to a bug in the compiler; try adding [self class]; or any other method call to self in that block and it'll probably work.
Works perfect, implementations of -didRetrieveItems and -errorRetrievingItems are in the super-class.
[self retrieveItemsForId:idString completionHandler:^(NSError *error) {
if (!error) {
[self didRetrieveItems];
} else {
[self errorRetrievingItems];
}
}];
I think you may be confused about one of the fundamental aspects of object oriented programming. You say that there are no implementations of those methods in your class, they exist only in the superclass.
Because of inheritance, your class effectively responds to said method calls, too. Just call 'em as you do above using self. It will work find and is exactly how you should be doing it!