Can we check if the object is nil or not, before going to release in dealloc method of a class - iphone

Can we check the object is nil or not before going to release in dealloc method. I am new to objective C. Is this right way to avoid segmentation issues?.
-(void)dealloc{
if(stringObject!=nil){
[stringObject release];
}
}

Testing for nil before release is fully redundant in Objective C and will not add any resiliency to your code.
Indeed, the whole point of segmentation faults (EXC_BAD_ACCESS) is having a pointer which is not nil, thus points to some memory, and accessing that piece of memory after it has been freed.
If the pointer is nil in the first place you will not be possibly able to access any memory with it and you will not have a segmentation fault in Objective C (unlike C or C++).
The real solution to segmentation faults is correct memory management. If retain/release management seems too complex, you can have a look at ARC, which has its own intricacies, though (although much less than manual retain/release management).

A simple
if(stringObject)
will do, if you just want to check if the variable points to an object.
But with Objective C it is not necessary to test for nil because an message to a null object will simply do nothing. So it is enough to say:
-(void)dealloc
{
[stringObject release];
stringObject = nil;
[super dealloc]; //added because of the comments
}
Under ARC, you can leave out the whole dealloc in most situations, because 1) the release is managed automatically, and 2) the call to dealloc is the made just before the object ends it's life, so the nil is not necessary. However, if you use custom c-style allocation you may still need an alloc method. But this belongs to an advanced topic.
Here's a link to the dev guide on working with objects in general:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1

This suffices as a nil test (your way is also correct, just slightly longer):
if (stringObject)
{
//do something
}
But in a simple case like yours, you don't even have to do that, because in Objective-C, sending messages to nil objects just means nothing happens:
[aNilObject doSomething]; //nothing happens, this is perfectly valid and won't throw an exception; it won't even log anything. Once you're used to it, it's great and avoids lots of boilerplate nil checks.
Going further, in your case, you should switch to ARC (after you're done learning manual retain and release, which is a good exercise).
Your code would then look like this:
//you don't need to call dealloc at all in ARC :)

Yes you can. Before ARC there was a very common macro defined
#define SAFE_RELEASE(object) if (object != nil) { [object release]; object = nil; }
NOTE: However, sending a message to nil will return nil.

Related

Object c property dealloc, which one is correct? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dealloc method in iOS and setting objects to nil
As to property dealloc in object c, i have seen different kinds of forms. Which of following is best/correct
//Kind1:
- (void)dealloc
{
[_property release];
[super dealloc];
}
//Kind2:
- (void)dealloc
{
self.property = nil;
[super dealloc];
}
//Kind3:
- (void)dealloc
{
[_property release]; _property = nil;
[super dealloc];
}
Your second option is inadvisable. Property setters may have side-effects and generally aren't implemented with the consideration that the object may be half torn down already. In general you should avoid any method calls to self (or super) from dealloc, other than [super dealloc]. You should also avoid non-trivial calls (i.e. anything but release) on other objects, as you may have circular references that can lead back to references to your half-deallocated object.
The first option is perfectly sufficient. Note that if you use ARC it is redundant. Using ARC is your best bet, invariably, as it's not only safer but faster.
The third option is controversial. Some people argue that it makes your program more resilient to errors (since references after dealloc may end at the zeroed instance variable, rather than bouncing through it and seg faulting, or worse). They also argue that it ensures that if you do run a method which tries to use the value, it'll probably fail gracefully (again, rather than dereferencing what is a dangling pointer at that point). But if you subscribe to my first point on avoiding this to begin with, it becomes somewhat moot. And my experience is that relying on that behaviour is a bad idea - even if it's a clean design to begin with, it's easy to forget about it and end up changing the code some time later, in a way that breaks it.
And those that dislike the third option also argue that it hides errors. Some go as far as explicitly overwriting not with nil but rather an obviously bogus value (e.g. 0x0badf00d) to make it clearer if and when a dangling pointer is dereferenced.
Kind1 is more than enough;
It is usually not a good idea to use 'self' on alloc and dealloc. coz self will call setter/getter method, and if u have custom setter/getter method its can cause trouble.
You should never call self. in dealloc.
Once you have release-ed then there is no advantage whatsoever of making it nil.
So, first one is the correct way to use dealloc.

What's the difference between setting an object to nil vs. sending it a release message in dealloc

I have Object:
MyClass *obj= [[MyClass alloc] init];
What's the difference between:
[obj release]; // Only obj own this object.
and:
obj = nil;
Does iOS deallocs obj when i set obj = nil?
I have a pointer, sometime i set it point to an object, sometime do not. So, when i want release a pointer i must check is it nil?
This answer from the previous decade,
is now only of historic interest.
Today, you must use ARC.
Cheers
The very short answer is DO NOT just set it to nil. You must release it. Setting it to nil has no connection to releasing it. You must release it.
However it's worth remembering that if it is a property, then
self.obj = nil;
will in a fact release it for you. Of course, you must not forget the "self." part !!!!
Indeed,
self.obj = anyNewValue;
will indeed release the old memory for you, clean everything up magically and set it up with the new value. So, self.obj = nil is just a special case of that, it releases and cleanses everything and then just leaves it at nil.
So if anyone reading this is new and completely confused by memory,
You must release it, [x release] before setting it to nil x=nil
IF you are using a property, "don't forget the self. thingy"
IF you are using a property, you can just say self.x=nil or indeed self.x=somethingNew and it will take care of releasing and all that other complicated annoying stuff.
Eventually you will have to learn all the complicated stuff about release, autorelease, blah blah blah. But life is short, forget about it for now :-/
Hope it helps someone.
Again note, this post is now totally wrong. Use ARC.
Historic interest only.
Is It Necessary to Set Pointers to nil in Objective-C After release?
Release, Dealloc, and the Self reference
Setting an object nil versus release+realloc
Read the above. They answer your Q comprehensively
iOS does not support garbage collection, which means that doing obj = nil would result in a memory leak.
If you want automatic control over deallocation, you should do something like: obj = [[[NSObject alloc] init] autorelease] (you must NOT release it if you do that).
Autorelease would cause the object to be automatically released when the current NSRunloop event ends.
The NSRunloop automatically drains it's NSAutoReleasePool for each event iteration, which is usually very helpful.
Setting an object nil will create a memory leak(if you are taking ownership by alloc,retain or copy) because we are not having a pointer to that particular memory location.
so if you want to dealloc an object you have to take out all ownership of an object before making it nil by calling release method.
[obj release];
obj=nil;

EXC_BAD_ACCESS on iPhone when using "obj != nil

I've got a very simple line of code in Objective-C:
if ((selectedEntity != nil) && [selectedEntity isKindOfClass:[MobileEntity class]])
Occasionally and for no reason I can tell, the game crashes on this line of code with an EXC-BAD-ACCESS. It usually seems to be about the time when something gets removed from the playing field, so I'm guessing that what was the selectedEntity gets dealloc'd, then this results. Aside from being impossible to select exiting Entities (but who knows, maybe this isn't actually true in my code...), the fact that I am specifically checking to see if there is a selectedEntity before I access it means that I shouldn't be having any problems here. Objective-C is supposed to support Boolean short-citcuiting, but it appears to not be EDIT: looks like short-circuiting has nothing to do with the problem.
Also, I put a #try/#catch around this code block because I knew it was exploding every once in a while, but that appears to be ignored (I'm guessing EXC-BAD-ACCESS can't be caught).
So basically I'm wondering if anybody either knows a way I can catch this and throw it out (because I don't care about this error as long as it doesn't make the game crash) or can explain why it might be happening. I know Objective-C does weird things with the "nil" value, so I'm guessing it's pointing to some weird space that is neither an object pointer or nil.
EDIT: Just to clarify, I know the below code is wrong, it's what I was guessing was happening in my program. I was asking if that would cause a problem - which it indeed does. :-)
EDIT: Looks like there is a fringe case that allows you to select an Entity before it gets erased. So, it appears the progression of the code goes like this:
selectedEntity = obj;
NSAutoreleasePool *pool = ...;
[obj release];
if (selectedEntity != nil && etc...) {}
[pool release];
So I'm guessing that because the Autorelease pool has not yet been released, the object is not nil but its retain count is at 0 so it's not allowed to be accessed anyway... or something along those lines?
Also, my game is single-threaded, so this isn't a threading issue.
EDIT: I fixed the problem, in two ways. First, I didn't allow selection of the entity in that fringe case. Second, instead of just calling [entities removeObjectAtIndex:i] (the code to remove any entities that will be deleted), I changed it to:
//Deselect it if it has been selected.
if (entity == selectedEntity)
{
selectedEntity = nil;
}
[entities removeObjectAtIndex:i];
Just make sure you are assigning nil to the variable at the same time you release it, as jib suggested.
This has nothing to do with short circuiting. Objective-C eats messages to nil, so the check for selectedEntity != nil isn't necessary (since messages-to-nil will return NO for BOOL return types).
EXC_BAD_ACCESS is not a catchable exception. It is a catastrophic failure generally caused by trying to follow in invalid pointer.
More likely than not, whatever object selectedEntity points to has been released before the code is executed. Thus, it is neither nil nor a valid object.
Turn on NSZombies and try again.
If your app is threaded, are you synchronizing selectedEntity across threads properly (keeping in mind that, in general, diddling the UI from secondary threads is not supported)?
Your post was edited to indicate that the fix is:
//Deselect it if it has been selected.
if (entity == selectedEntity)
{
selectedEntity = nil;
}
[entities removeObjectAtIndex:i];
This fixes the issue because the NSMutableArray will -release objects upon removal. If the retain count falls to zero, the object is deallocated and selectedEntity would then point to a deallocated object.
if an object (selectedEntity) has been released and dealloc'd it is not == nil. It is a pointer to an arbitrary piece of memory, and deferencing it ( if(selectedEntity!=nil ) is a Programming Error (EXC_BAD_ACCESS).
Hence the common obj-c paradigm:-
[selectedEntity release];
selectedEntity = nil;
i just read this http://developer.apple.com/mac/library/qa/qa2004/qa1367.html which indicated that the error you are getting is a result of over-releasing the object. this means that altough selectedEntity is nill, you released it to many times and it just not yours to use anymore..
Put a breakpoint on OBJC_EXCEPTION_THROW and see where it is really being thrown. That line should never throw a EXC_BAD_ACCESS on its own.
Are you perhaps doing something within the IF block that could cause the exception?
selectedEntity = obj;
NSAutoreleasePool *pool = ...;
[obj release];
if (selectedEntity != nil && etc...) {}
[pool release];
You have a dangling pointer or zombie here. The selectedEntity is pointing at obj which gets releases right before you reference selectedEntity. This makes selectedEntity non-nil but an invalid object so any dereference of it will crash.
You wanted to autorelease the obj rather than release it.

iPhone - dealloc - Release vs. nil

Wondering if someone with experience could possibly explain this a bit more. I have seen examples of...
[view release];
view = nil;
....inside the (void) dealloc.
What is the difference and is one better then the other?
What is the best way?
When doing retainCount testing I have personally seen nil drop a count from 3 to 0 for me, but release only drops it from 3 to 2.
What you have seen is probably these:
1) [foo release];
2) self.bar = nil;
3) baz = nil;
Is releasing the object, accessing it through the instance variable foo. The instance variable will become a dangling pointer. This is the preferred method in dealloc.
Is assigning nil to a property bar on self, that will in practice release whatever the property is currently retaining. Do this if you have a custom setter for the property, that is supposed to cleanup more than just the instance variable backing the property.
Will overwrite the pointer baz referencing the object with nil, but not release the object. The result is a memory leak. Never do this.
If you are not using properties (where self.property = nil will also release an object) then you should ALWAYS follow a release by code that sets the reference to nil, as you outlined:
[view release]; view = nil;
The reason is that it avoids he possibility that a reference can be used that is invalid. It's rare and hard to have happen, but it can occur.
This is even more important in viewDidUnload, if you are freeing IBOutlets - that's a more realistic scenario where a reference might go bad because of memory warnings unloading a view, and then some other code in the view trying to make use of a reference before the view is reloaded.
Basically it's just good practice and it will save you a crash at some point if you make it a habit to do this.
#bbullis22 you have seen the restain count drop from 3 to 0 because you set the reference to nil. then you asked for the retaincount of 'nil' which is zero. however, the object that used to be referenced has the same retain count - 1 (due to setting the reference to nil).
using release, the reference still references the same object, so that's why you see the retain count drop from 3 to 2 in this situation.
As far as usage inside your code, in your dealloc you don't need the assignment to the property, releasing is all you need to do.
- (void)dealloc {
[myProperty release]; // don't need to assign since you won't have the object soon anyway
[super dealloc];
}
I think using both is kind of safety net. With only release in place you could run in problem if you screwed reference counting management. You would release an object, giving its memory back to system but pointer would be still valid.
With nil you are guaranteed that program will not crash since sending message to nil does nothing.

Why should a self-implemented getter retain and autorelease the returned object?

Example:
- (NSString*) title {
return [[title retain] autorelease];
}
The setter actually retained it already, right? and actually nobody should bypass the Setter... so I wonder why the getter not just returns the object? It's actually retained already. Or would this just be needed in case that in the mean time another objects gets passed to the setter?
From here http://www.macosxguru.net/article.php?story=20030713184140267
- (id)getMyInstance
{
return myInstanceVar ;
}
or
- (id)getMyInstance
{
return [[myInstanceVar retain] autorelease] ;
}
What's the difference ?
The second one allows the caller to get an instance variable of a container object, dispose of the container and continue to play with the instance variable until the next release of the current autoreleased pool, without being hurt by the release of the instance variable indirectly generated by the release of its container:
aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);
If the "get" is implemented in the first form, you should write:
aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];
The first form is a little bit more efficent in term of code execution speed.
However, if you are writing frameworks to be used by others, maybe the second version should be recommanded: it makes life a little bit easier to people using your framework: they don't have to think too much about what they are doing…;)
If you choose the first style version, state it clearly in your documentation… Whatever way you will be choosing, remember that changing from version 1 to version 2 is save for client code, when going back from version 2 to version 1 will break existing client code…
It's not just for cases where someone releases the container, since in that case it's more obvious that they should retain the object themselves. Consider this code:
NSString* newValue = #"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue
This looks reasonable, but if neither the setter nor the getter uses autorelease the "Go on to do something" part will likely crash, because oldValue has now been deallocated (assuming nobody else had retained it). You usually want to use Technique 1 or Technique 2 from Apple's accessor method examples so code like the above will work as most people will expect.
Compare this code
return [[title retain] release]; // releases immediately
with this
return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier)
The second one guarantees that a client will have a non-dealloced object to work with.
This can be useful in a situation like this (client code):
NSString *thing = [obj title];
[obj setTitle:nil]; // here you could hit retainCount 0!
NSLog(#"Length %d", [thing length]); // here thing might be dealloced already!
The retain (and use of autorelease instead of release) in your title method prevents this code from blowing up. The autoreleased object will not have its release method called until AFTER the current call stack is done executing (end of the current run loop). This gives all client code in the call stack a chance to use this object without worrying about it getting dealloc'ed.
The Important Thing To Remember: This ain't Java, Ruby or PHP. Just because you have a reference to an object in yer [sic] variable does NOT ensure that you won't get it dealloc'ed from under you. You have to retain it, but then you'd have to remember to release it. Autorelease lets you avoid this. You should always use autorelease unless you're dealing with properties or loops with many iterations (and probably not even then unless a problem occurs).
I haven't seen this pattern before, but it seems fairly pointless to me. I guess the intent is to keep the returned value safe if the client code calls "release" on the parent object. It doesn't really hurt anything, but I doubt that situation comes up all that often in well-designed libraries.
Ah, ok. from the documentation smorgan linked to, it seems this is now one of the methods that Apple is currently recommending that people use. I think I still prefer the old-school version:
- (NSString *) value
{
return myValue;
}
- (void) setValue: (NSString *) newValue
{
if (newValue != myValue)
{
[myValue autorelease]; // actually, I nearly always use 'release' here
myValue = [newValue retain];
}
}