3

I have started to study Three20 and I have a simple question about TT_RELEASE_SAFELY Up till now I like to write code in this way:

UILabel *lab = [[UILabel alloc] initWithFrame:rect];
[self.view addSubview:lab];
[lab release];

Here I think the main pool is responsible to free the memory of lab.

Now I have found TT_RELEASE_SAFELY which is defined like so:

#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER release]; __POINTER = nil; }

As you can see, after release, it sets the object to nil.

I'd like to know the difference between the two ways and which way is better.

Thanks.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
scorpiozj
  • 2,687
  • 5
  • 34
  • 60

3 Answers3

6

Sending a message to nil is valid in Objective-C. Sending a message to a deallocated object is not.

Sending a message to a deallocated object:

id obj = [[MyClass alloc] init];
[obj release];
[obj doSomething]; // Crash!

Sending a message to nil:

id obj = [[MyClass alloc] init];
[obj release], obj = nil;
[obj doSomething]; // Valid

Assigning nil to a variable after an object has been deallocated is controversial because it can prevent you from realizing that something is wrong. Sedate Alien's example:

[controlCenter dealloc];
...
float timeLeft = [controlCenter timeToWaitBeforeBombDetonation];

This code will crash since controlCenter has been deallocated. As a result this defect will be detected and fixed early.

[controlCenter dealloc], controlCenter = nil;
...
float timeLeft = [controlCenter timeToWaitBeforeBombDetonation];

This code will assign 0.0 to timeLeft which appears to be a valid wait time even though controlCenter is nil.


Take the above with a grain of salt, since if you are writing an Objective-C app, you are probably more concerned with keeping your users happy by avoiding crashes than destroying cities. If the latter is a concern, you should probably be using a type-safe language like Ada.

Community
  • 1
  • 1
titaniumdecoy
  • 18,900
  • 17
  • 96
  • 133
  • I think so, and it is some kind of a best practice! – scorpiozj May 12 '11 at 03:02
  • By "valid", I assume you mean "won't crash at this particular point". It won't "do something" (as the name implies), perhaps it should be `[obj wontDoAnything];` instead? – Aidan Steele May 12 '11 at 03:04
  • @Sedate Alien: It won't do anything in terms of the method not being called, but it will give you a valid return value (0, NO, etc.) if you choose to use it. – titaniumdecoy May 12 '11 at 03:08
  • @titaniumdecoy: It will give you a **a** return value, not necessarily a valid one. Perhaps `NO` should only be returned after some action is taken, etc. What about `NSZombieEnabled`? Nilling out references means it will be no help to you in debugging. – Aidan Steele May 12 '11 at 03:22
  • @Sedate Alien: You are correct, nilling out references can make debugging more difficult, which is why I didn't say it was a good idea. However, sending a message to nil *will* give you a valid, predictable return value; see the link in my post. – titaniumdecoy May 12 '11 at 03:27
  • @titaniumdecoy: I don't disagree that the return value is predictable, nor that it is of the correct type. What I meant is that one might send `-[NSControlCenter timeToWaitBeforeBombDetonation:]` and get `0.0` in return from `nil`, hence detonating the bomb when it is not correct to do so. I think you should edit your post to say it isn't a good idea, because @scorpiozj seems to think it is. – Aidan Steele May 12 '11 at 03:34
  • @titaniumdecoy,@Sedate Alien:thank both of you. In my understanding Sedate Alien means calling a function of nil object will cause confusing result which makes debugger difficult as you don't know the "return" is valid or not. However as for the memory management I think it is a good pattern and I can't find the shortcoming. Any tips? @titaniumdecoy:what do you mean by pointless? I believe it is safe:checking an object whether it is nil before using it and using TT_RELEASE_SAFELY if you think you will no longer use it. – scorpiozj May 12 '11 at 04:29
1

I believe that using these variants of "safe releases" is an expressly bad idea.

Your application will fail in silent and mysterious ways, as messages passed to nil will not raise any warnings. It's much better to not nil out your references and take advantage of all that NSZombieEnabled has to offer.

Aidan Steele
  • 10,999
  • 6
  • 38
  • 59
0

The only difference is that TT_RELEASE_SAFELY sets the pointer to nil after release, so the reference won't be used after release. The pattern is a good one to follow and the TT_RELEASE_SAFELY macro makes it simpler to implement.

ThomasW
  • 16,981
  • 4
  • 79
  • 106