开发者

Objective-C: Memory-wise, what do I need to do with other pointers to a released object?

开发者 https://www.devze.com 2023-01-20 05:41 出处:网络
For example say I have: NSMutableArray *array = [[NSMutableArray alloc] init]; NSMutableArray *array2 = array;

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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消