iphone - testing if an object exists - iphone

I have several objects in my app that can become nil at some point and I have methods that in theory are used to put these objects to nil.
But, if I try to put to nil an object that does not exist, the app will crash.
for example...
[object1 release];
object1 = nil;
//... and after that
[object1 removeFromSuperview]; // this will crash
Then I thought, why not testing to see if the object exists before removing...
if (object1 != nil)
[object1 removeFromSuperview];
// this will crash too, because object1 cannot be tested for nil because it does not exist
How can I check if the object exists before testing if it is nil?
something as
if (object1 exists( {
if(object1 != nil))
[object1 removeFromSuperview)
}
is this possible?
I ADDED THIS TO CLARIFY...
what I mean is this: imagine I have object1 declared on the header and initialized on the code. So, it exists and points to a valid reference. At some point, the object may be released, so the reference still points to an object but the object was freed. Even if I put the object to nil after releasing, I cannot do anything with it.
The problem is this: I have some methods that are asynchronous. One of them scans for some objects and remove them if they are found. I must check if the object exists and the reference points to a valid object before releasing it again. This is the point: how do I test if the object exists and its reference points to a valid existent object before releasing it again, to void releasing again an object that is already released and crash the app.

In short, your question of determining if the pointer is still valid is going down the wrong path.
After you release an object, you must immediately set its value to null so that you no longer control it. If two methods are running asynchronously accessing the same object, they must be synchronized at that point so that releasing and setting to null happens at the same time in one thread before the other has a chance to interrupt.

Are you just speculating, or have you actually tried this? Because in other programming languages, invoking a method on nil will cause a crash. In Objective-C this is not true. In Objective-C, you CAN send messages to nil without causing a crash. These messages simply have no effect.
In fact, you can be really obscene and do the following without a crash:
[(id)nil setTitle:#"Testing"]; // This will not cause a crash
If your app is crashing, it is not because you are messaging nil. It is possible, however, that you are failing to set a pointer to nil and you are messaging an object in memory that you do not own. Given the details you provided in your update, namely that you have an asynchronous thread accessing these objects, I think it is very likely you are sending messages to pointers whose object has already been released, but have not yet been set to nil.

I have compared an object to nil before without any problems.

Related

Using weak reference to check if object is deallocated, in Objective-C

I'm using ARC.
Sometimes I wrote the following code to assert a object should be deallocated:
__weak weakVariableOrProperty = someObject;
....
someObject = nil;
// or someObject = anotherObject;
....
if (weakVariableOrProperty) {
#throw [NSException exceptionWithName:NSInternalInconsistencyException reason:#"Object not deallocated" userInfo:nil];
}
For example, I use this code to check if a view controller is deallocated before creating a new view controller.
I believe that weak variable or weak property is set to nil immediately after last strong variable or property was set to nil or another object.
And this code is working as I expected until now.
Using weak variable or property to check if object is deallocated is a technique commonly used?
Is it possible that this code will cause problem in the future?
I believe that weak variable or weak property is set to nil immediately after last strong variable or property was set to nil or another object.
This is not exactly true, because an object could be autoreleased. In this case, the last strong reference may be gone, but the reference count of the instance would remain positive. In cases like that, the __weak reference would not be nil-ed out until the autorelease process takes place.
Is using weak variable or property to check if object is deallocated a technique commonly used?
I seriously doubt that this technique has gained much popularity, because ARC is a relatively new thing to Objective C. However, the technique appears valid.
Is it possible that this code will cause problem in the future?
This is very hard to guess, because the ARC Specification does not make any specific guarantees about the timing of nil-ing out the references, and because the spec allows compilers to optimize sequences of retain and release messages that they send to ARC objects.
Your explanation code will be prone to a race condition.
The object in weakVariableOrProperty could be released (since it's only referenced by a weak reference) after the if condition has been evaluated. To avoid this, introduce an ordinary variable, set it to weakVariableOrProperty and check it for nil instead.
That said, as #dasblinkenlight says, betting on exactly when an object will be gone is tough. In a reference-counted system you don't know what else is holding onto it. It may go away just after you've checked. You should be able to constrain your environment enough that you know the system's not squirreling things away, but both autorelease and weak references complicate things.
The best way to solve this is simply to have well-defined object lifetimes: view controllers that don't live forever, that you explicitly tell to go away and so on.
So I've tried using this technique to ensure that objects are always deallocated on a background thread. The [dealloc] for some of my classes was moderately heavy weight and could take a long time (10s of ms) which would freeze the main thread ever so slightly.
I decided to add all of these heavy objects to an array before they'd be released on the main thread, and then go through that array later on a backgroundd thread to remove them from the array. The thought was that the array would keep the retainCount alive until it could be removed from the array on the background thread, and then i could guarantee the cost of the [dealloc] wouldn't happen on the main thread.
To do this, i had the code below:
while([objectsToDealloc count] && /* other conditions to prevent infinite loop */){
__weak id ref = [objectsToDealloc lastObject];
[objectsToDealloc removeLastObject];
#synchronized(ref){
// synchronising on ref will retain it if possible.
// so if its still around,that means we didn't dealloc it
// like we were asked to.
// so insert it back into our array. once the object is deallocd
// it won't be able to be synchronized, because the weak ref will
// be nil
if(ref){
[objectsToDealloc insertObject:ref atIndex:0];
}
}
}
The idea was that if the array didn't contain the last reference (or if there were pending autoreleases on the object, etc), then the weak ref wouldn't nil out. I'd then #synchronize on the object - the synchronized block will retain + release whatever object is being synchronized - which would ensure the ref would stay alive during that block. if it was nil, then it'd been dealloced. if it wasn't nil, then i should add it back to the array and check back again later.
After testing with this code over the past few weeks, I cannot recommend this strategy to check for deallocated objects. I haven't tracked down exactly why yet, but very rarely the object will dealloc but the ref won't be nil yet, so i'll be adding an invalid object back into the array.
i've only caught this in the debugger one time, though i have crash logs of it happening a few times. You can see below that "nil" ends up in my array, even though the code above should protect against it.
Again, I suggest not using this technique for detecting when/if objects deallocate, and instead focus efforts on clarifying your object graph and relationships.

Why should I do [object release]; object=nil; when deallocating an object?

I would like to understand why it could be useful to do this (assuming "object" was previously allocated):
[object release];
object=nil;
Thx for helping,
Stephane
Even though you release an object, your variable will still point to something. What it points to is undefined. It could still point to the old object, or to some point in memory. Setting it to nil avoids sending messages to whatever it points to, and prevents errors (messaging nil does nothing).
Here's an answer that states it better: Setting pointers to nil, objective-c
If you just released it, object would still point to the memory address that it had before. If you checked it to be nil (object == nil) it would return NO. It is better to make sure that it points to nil after you release it.
This mostly has to do with multi threading, if an other thread tries to access the object you released and set to nil it will not crash. You can send message to nil object and it will just do nothing.
But if it is just deallocated you are sending a message to the deallocated object and your app will crash.
Here is nice reading material:
http://iphonedevelopment.blogspot.com/2010/09/dealloc.html
http://www.red-sweater.com/blog/1423/dont-coddle-your-code

iPhone - Is there a way to know if a reference is (still) valid?

Let's say I assign an instance var with an object given in parameter. I don't know what this object is, so I don't want to retain it. But, that reference I have to that object can be invalid at some time, for example if the object is released, or is about to be released (autorelease pool). So, inside my class instance, can I know if the reference I have kept into an instance variable can be used without any risk of crash?
You should retain it and release it when you no longer need it. That is exactly what retain is for.
Kris Van Bael is right, no matter if you know what the object is, if you want to have ownership of it (if it's up to you to ensure that the object is alive), you must retain it. Release it when you don't need it, and set the reference to NIL (for security).
But their is an exception !
Sometimes you don't want to have ownership, the most common example is the delegate.
You don't want to retain your delegate, because it probably already retains you, and if both objects release each other in the dealloc method, your app will leak.
But in this case, you shouldn't care about the delegate being deallocated : the delegate should set your "delegate" property to nil in it's dealloc method.
So
if you have ownership on the object : retain, no choice !
if the object has ownership on you : assign, and don't worry !
This approach is really dangerous. If your app is not able to track object life cycle, then you must change the code in order to have control of this.
Anyway answering to your question: you can protect your instance variable by extra retaining it in your class and then releasing it when it is no more needed. So you don't need to do the check you are asking for.
You should set any released reference to NIL and check for NIL.

Objective-C pointers/memory management question

I am testing the following code below. ffv is declared in the interface file.
ffv = [[FullFunctionView alloc] initWithFrame:self.view.bounds];
NSLog(#"%i", [ffv retainCount]); // prints 1
[self.view insertSubview:ffv belowSubview:switchViewsBtn];
NSLog(#"%i", [ffv retainCount]); // prints 2
[ffv release]; // you can release it now since the view has ownership of ffv
NSLog(#"%i", [ffv retainCount]); // prints 1
if (ffv == nil)
NSLog(#"ffv is nil");
// "ffv is nil" is not printed
[ffv testMethod]; // "test method called" is printed
this is my [ffv testMethod] implementation
- (void)testMethod
{
NSLog(#"test method called");
}
What I deduce in this case is that even if you release an object with retain count 2, you lose ownership of that object however, the reference is still kept.
Now, my question are:
Is my deduction correct?
Is there anything else important that can be deduced from this?
What are the complications caused by still keeping (using) ffv and calling methods from ffv? (My opinion is that this is ok since the view will always own ffv and won't release it until someone calls viewDidUnload. And as long as I don't pass ffv's reference to other objects.)
There are a couple of problems with using ffv after you have released it and it's only retained by your view controller's view.
1) It introduces a potential for future bugs, because later you might not remember that ffv is otherwise not retained. When you release the view (e.g. by replacing it with another view), you have a dangling pointer that you still hold a reference to.
2) In the special case of a UIViewController the view could be released at any time (you usually never call viewDidUnload yourself). The default behavior of UIViewController, when receiving a memory warning and the view is currently not visible, is to release the view, so unless you set the reference to nil in viewDidUnload, you have a dangling pointer again, even though you never explicitly released the view yourself.
1) Is my deduction correct?
Your deduction is correct. The Memory Management Programming Guide explains that each object has one or many owners. You own any object you create using any method starting with alloc, new, copy, or mutableCopy. You can also take ownership of an object using retain. When you're done with an object, you must relinquish ownership using release or autorelease.
Releasing the object doesn't change the value of any variables that reference that object. Your variable contains the object's memory address until you reassign it, no matter what retain count the object has. Even if the object's retain count goes to zero, causing the object to get deallocated, your variable will still point at that same address. If you try to access the object after it's been deallocated, your app will normally crash with EXC_BAD_ACCESS. This is a common memory management bug.
2) Is there anything else important that can be deduced from this?
Nothing comes to mind.
3) What are the complications caused by still keeping (using) ffv and calling methods from ffv? (My opinion is that this is ok since the view will always own ffv and won't release it until someone calls viewDidUnload. And as long as I don't pass ffv's reference to other objects.)
When you call release, you are telling the Objective C runtime that you no longer require access to the object. While there may be many cases like this one in which you know the object will still exist, in practice you really shouldn't access an object after calling release. You'd just be tempting fate and setting yourself up for future bugs.
I personally don't like peppering my code with release statements, because I don't trust myself to remember them 100% of the time. Instead, I prefer to autorelease my variables as soon as I allocate them like this:
ffv = [[[FullFunctionView alloc] initWithFrame:self.view.bounds] autorelease];
This guarantees that ffv will exist at least until the end of the method. It will get released shortly thereafter, typically before the next iteration of the run loop. (In theory this could consume excessive memory if you're allocating a large number of temporary objects in a tight loop, but in practice I've never encountered this case. If I ever do, it will be easy to optimize.)
The object is not deallocated until the retain count goes to 0. As long as it's not deallocated, you can keep using it without trouble. By retaining it you ensure that it won't be deallocated under your feet; however, if you retain another object that you know retains the first object, you can get away with this form of "indirect retaining". Don't complain when you move things around later and things start breaking, though.
if (ffv == nil)
NSLog(#"ffv is nil");
// "ffv is nil" is not printed
That's correct, releasing an object does not set the pointer to nil even if it is dealloced at that time. Good practice is to always set your pointer to nil after you release it.
You are correct to say that after you released it, it wasn't dealloced because the view still had a retain on it. But that's not how you should be thinking about it. If you want to use that object and you want it to be alive, retain it. Doesn't matter who else is retaining it. Your object has nothing to do with those other objects. You want it, retain it. You're done with it, release it and set your pointers to nil. If you don't set it to nil and everyone else also released it, you will have a dangling pointer to an object that was dealloced, and that will cause you a crash and much grievance.
so this:
[ffv release]; // you can release it now since the view has ownership of ffv
ffv = nil; // you released it, so that means you don't want it anymore, so set the pointer to nil
if you still want to use it, don't release it until you're done with it.
Well, I'm not sure 'losing' ownership is the right term. In Objective-C you have to carefully marshal your ownership of the object. If you create or retain an object, you are responsible for releasing it (either directly or via an autorelease pool). When you call release however, you don't lose a reference to the object, if something else has retained it, it will still be in memory, and your pointer will still potentially point to it.
You have a pointer ffv which is just a pointer to some memory, and you have the object which is created in the first line that ffv points to.
By calling release, you are stating that you no longer require the ponter ffv to point to a valid object, that in this context you would be happy for the object to be deallocated. The pointer still points to that bit of memory, and it is still there because its retain count was increased by assigning it to the view.
The line [ffv testMethod] is in danger of not working, as it follows the release and may not point to a valid object. It only works because something else is keeping it alive. ffv still has the same address value that it had when it was first assigned.
So in order:
Your deduction is correct.
Not really.
You shouldn't use ffv after the release call. You have no guarantee that the object is going to be there for you.
These are pointers we are using here, not references like you find in Java or C#. You have to marshal your ownership of the object, you create it, have some pointers to it and by careful management of retain and release calls you keep it in memory for as long as you need it.

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.