jlpiedrahita
jlpiedrahita

Reputation: 497

Objective-C - Test for object instance being dealloced/freed

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!!

Upvotes: 7

Views: 17239

Answers (6)

user23743
user23743

Reputation:

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

Update: For XCode 4.0 see How to enable NSZombie in Xcode?

Upvotes: 13

john ellis
john ellis

Reputation: 2164

would a "try-catch" work?

 @try {
      [b description]; // test it... 
 }
 @catch (NSException * e) {
    NSLog(@"Exception: %@", e);
 }
 @finally {
    NSLog(@"finally");
 }

Upvotes: -2

Quinn Taylor
Quinn Taylor

Reputation: 44769

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.

Upvotes: 3

Abizern
Abizern

Reputation: 150605

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

Upvotes: 0

Alex Brown
Alex Brown

Reputation: 42872

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.

Upvotes: 2

Chuck
Chuck

Reputation: 237030

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.

Upvotes: 11

Related Questions