For example say I have:
NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableArray *array2 = array;
[array release];
is this legal? Do I just leave array2 dangling since I already released the object that was taking memory?
For example say I have:
NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableArray *array2 = array;
[array release];
is this legal? Do I just leave array2 dangling since I already released the object that was taking memory?
As you suspect, array2 no longer refers to a valid object after you call [array release]
.
However, it's not clear what the value having of the second variable is. It would not be available to you anywhere that array
isn't already available (they have the same scope), and since they both refer to the same object, you might as well just use one variable.
If you need a second array, or another reference that is valid after [array release]
, you could create a copy, or use NSMutableArray *array2 = [array retain]
. Either way, you would need to release array2 at some point to avoid a memory leak.
Variables array and array2 are merely C pointers to a chunk of memory. As with any heap-allocated chunk of memory in C, it has to be malloced() and freed(), which effectively determine the lifetime of the memory chunk in the absence of garbage collector. Obj-C objects are a little specialized chunks of memory, but the underlying mechanics is the same: a variant of calloc() and free().
So yes, after you send [array release] the array object's retain count reaches zero and the object immediately sends -dealloc to self, which calls free(). After that any attempt to access the chunk of memory occupied by the object will cause a crash (or worse yet, if another Obj-C object gets allocated at the same address, you will get crashes in unrelated places all over your code).
Since array2 is just another pointer to the same, now freed, chunk of memory, you can't do anything with it either. The best you can do is set such pointers to nil to prevent yourself from accidentally accessing memory you no longer own. Obj-C is smart enough to make messages sent to nil (messages sent to nil pointers) no-ops.
You don't have do do anything!
The 'other' pointers are no different to the original pointer. They all point to the same thing. They are exactly equivalent to each other.
The thing to understand is that release
has no effect on the pointer itself. I get the impression you think [array release]
somehow does something to the array
pointer leaving it somehow altered. It doesn't. Consider this code:
NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableArray *array2 = array;
[array2 release];
This is exactly equivalent to your code and just as legal. You can call release on either array
or array2
and it has the exact same effect. Neither array
or array2
is changed by the call. Only the object pointed to.
So there is no point retaining twice only to release twice. At the end of it, you are left with exactly the same situation: two pointers to a freed object.
You can nil them out if you want, but it's not necessary.
Is this not just a question of code cleanliness?
If you want array2 to point to array, and you're going to be doing some work with array2, then I'd explicitly retain it:
NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableArray *array2 = [array retain];
[array release];
[array2 release];
This way, if someone else decides to do some work with array2 after [array release] is called, they won't run into memory problems.
Your original code is valid, but contains a nasty surprise for anyone using array2 after release is called.