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

17,149

Solution 1

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.

Solution 2

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.

Solution 3

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.

Share:
17,149
jlpiedrahita
Author by

jlpiedrahita

Updated on June 24, 2022

Comments

  • jlpiedrahita
    jlpiedrahita almost 2 years

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

  • Quinn Taylor
    Quinn Taylor almost 15 years
    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.
  • Chuck
    Chuck almost 15 years
    The tags say Cocoa Touch, so he's not on Leopard.
  • Quinn Taylor
    Quinn Taylor almost 15 years
    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.
  • jlpiedrahita
    jlpiedrahita almost 15 years
    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.
  • Chuck
    Chuck almost 15 years
    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.
  • Dan Rosenstark
    Dan Rosenstark over 12 years
    pretty sure calling a message on a dealloced instance does NOT throw a normal exception bur rather a sigbart.