我们真的需要安全发布宏吗?

时间:2011-02-21 16:37:14

标签: objective-c

很多人似乎都在使用像

这样的宏
#define SAFE_RELEASE(X)  [X release]; X = nil;

(包括我自己)。

我一直在重新评估我为什么要使用它,并希望画出一些意见。

使用这个宏的目的(我认为)是这样的,如果你在发布它之后意外地使用你的对象,那么你将不会得到一个糟糕的访问异常,因为objective-c会相当当对象为零时,请高兴地忽略它。

我觉得这有可能掩盖一些不起眼的错误。当你再次尝试使用X时,程序实际上可能会崩溃。在测试期间,您可以找到问题并改进代码。

这个宏是否鼓励懒惰编程?

思想?

5 个答案:

答案 0 :(得分:6)

我认为你在讨论你的问题中的所有优点和缺点,所以我没有大量的补充。我个人不使用该构造。正如您所建议的那样,可以用于记录人们无法正确理解内存管理的区域。我的偏好是修复bug而不是症状。

然而,我不时看到的一个妥协是:

  • 在开发期间使其崩溃
  • 执行生产代码中的var = nil;

这样,可能对付费客户更可靠,并且在开发过程中仍然会早期崩溃。

我也不是很喜欢这个,因为你正在为你的用户使用不同的代码,只是因为错误的版本一直在运行并不意味着它正在做正确的事情。没有崩溃但是破坏你的数据库不是理想的行为......

答案 1 :(得分:2)

我认为,或者像self.myVar = nil这样的等价物,如果适用的话,是好的。在许多情况下,您根本无法分配nil并假设任何后续访问都是错误。

例如在UIKit中,当操作系统询问时,释放尽可能多的资源是一种很好的行为。 E.g。

- (void)didReceiveMemoryWarning 
{
    [myCachedData release];
    [super didReceiveMemoryWarning];
}

现在,当我下次使用我的课时,我怎么知道myCachedData现在无效?唯一的方法(没有ANOTHER变量作为标志)是在释放后将myCachedData设置为nil。将这两条繁琐的线条合并为一条正是SAFE_RELEASE的用途。

答案 2 :(得分:1)

你没有需要它,但它很方便。我在我的应用中使用类似的东西。你可以认为它是“懒惰的”,但当你有大约20个对象时,手动编写这些对象变得乏味。

答案 3 :(得分:1)

我正在研究同样的问题。随着阅读的一点点,我做了类似的事情:

#define DEBUGGING
    //#define PRODUCTION

#ifdef DEBUGGING
#define SAFE_RELEASE(X)  [X release]; 
#else
#define SAFE_RELEASE(X)  [X release]; X = nil;
#endif

因此,如果我正在开发,我会得到崩溃。在生产中我没有。

斯科特< -

答案 4 :(得分:1)

正如安德鲁所指出的那样,在某些情况下,分配nil不仅可以避免错误,而且是必要的。只需考虑典型的UIViewController代码

- (void)viewDidLoad {
  button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // autoreleased
  [button retain]; // keep alive
}

- (void)viewDidUnload {   // view has been removed
  [button release];
}

- (void)dealloc {     // destroying the view controller
  [button release];   // <-- problem
}

如果加载控制器,稍后卸载(因为显示另一个视图控制器,内存运行不足)并最终销毁,[button release]中的dealloc将过度释放按钮(发送一个消息发布的对象)。因此,有必要指定nil。安全的解决方案是:

- (void)viewDidUnload {   // view has been removed
  [button release];
  button = nil;
}

- (void)dealloc {     // destroying the view controller
  [button release];   // <-- safe
}

对于那些情况,宏很好用。为了更明确地说明它的作用,最好将其命名为RELEASE_AND_NIL

#define RELEASE_AND_NIL(X)  [X release]; X = nil;