views:

1892

answers:

5

There's some way to test for an objective-c instance for being dealloced/freed (retain count == 0)??

By example, object A have a reference (pointer) to object B, but object B can be freed in memory low levels, how i test reference B to be sure it was dealloced??

@interface A : NSObject {
    B b;
}

@implementation A {

- (void) someAction:(id) sender {
    //is b previously dealloced?? 
    if ..... ???? {
        b = [[B alloc] init];
    }
    // continue
}
}

Thanks!!

+5  A: 

You can't test whether an object has been dealloced since, obviously, the object isn't there to talk to anymore. If you set b to nil when you release it (say, by doing self.b = nil), though, you can test for nil and create the object then.

Chuck
that's the problem, i don't release the object explicitly, it's released by framework classes and this don't happen to predictable times (ex. didReceiveMemoryWarning: method calls) so i need to test if my reference (pointer) is still pointing to a valid instance, if not, alloc and init a new one.
jlpiedrahita
What framework class is releasing this class's instance variable? Why doesn't this class own its own ivar? I think you might need to provide more info in the question. As Alex said, your attributes shouldn't be mysteriously disappearing.
Chuck
+2  A: 

If you retain b properly, it will not be deallocated in low memory conditions.

That is, unless you are deallocating it yourself, in which case it is important that you manually remove any references to it before you do so (by replacing it with nil)

In that case, simply testing it for the nil value will do:

  if (nil == b)
  { 
    reallocate b;
  }

If it seems like your objects are being deallocated automatically, then you need to review your code to check you have retained it sufficiently.

Alex Brown
A: 

You could try putting NSLog messages in the objects dealloc method. That will at least tell you when the object is being released.

Abizern
That won't work for a test in code to see if the object has been deallocated. At best, it would help debug that the retain-release code related to B is (probably) correct.
Quinn Taylor
+2  A: 

Since the variable b is completely internal to class A, and is not declared as @public (the default is @protected), the best way to know if b has been deallocated is to release it and set the pointer to nil. That way, you can just check if (b == nil) and create a new instance if necessary.

The bigger question, however, is what the true nature and memory behavior of b is. You state that "object B can be freed in memory low levels", but don't explain why. If you're using the standard idioms for retain-release in Objective-C, I would think that A would be the one to determine whether B should be deallocated, since it's creating a new instance. If you don't intend for A to make such decisions, allowing it to allocate a new B will lead to ownership confusion and memory bugs down the road.

If A is not in charge of B, and if you are on Leopard (or beyond) and have garbage collection enabled, what you may want is a zeroing weak reference. This is declared using __weak before an instance variable declaration, and doesn't prevent the garbage collector from collecting the object it points to. (A "strong" reference is the default, and the garbage collector won't deallocate object it can trace from a root through only strong references.) Further, the GC will automatically set weak references to 0 for you if/when the object is deallocated.

Coming back to "the bigger question", unless b is already a weak reference and GC is on, (and a few other conditions hold), the system will not automatically deallocate B for you. If the reason for deallocating b is that instances of B grow over time, (such as a cache of dispensable items), it would be much better to have a way to empty B. For example, mutable collections in Foundation have a -removeAllObjects method. Such an approach would avoid most of the confusion about whether b still exists, and is much more efficient than repeatedly (de)allocating objects.

Quinn Taylor
The tags say Cocoa Touch, so he's not on Leopard.
Chuck
One of the tags is also "Cocoa", and the question didn't specify iPhone, so I though it best to be general and qualify with "if" to be helpful to those who may be on Leopard.
Quinn Taylor
+2  A: 

If you set the NSZombieEnabled environment variable, then dealloced objects become instances of NSZombie. These throw when they are next messaged, causing your code to crash and burn - exactly what you need to debug this situation.

http://www.cocoadev.com/index.pl?DebuggingAutorelease

Graham Lee