【问题标题】:Setting object to nil after release -- TT_RELEASE_SAFELY释放后将对象设置为零——TT_RELEASE_SAFELY
【发布时间】:2011-05-12 02:17:11
【问题描述】:

我已经开始学习 Three20 并且有一个关于TT_RELEASE_SAFELY 的简单问题 直到现在我都喜欢这样写代码:

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

这里我认为主池负责释放lab的内存。

现在我找到了TT_RELEASE_SAFELY,它的定义如下:

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

如您所见,发布后,它将对象设置为nil。

我想知道这两种方式的区别,哪种方式更好。

谢谢。

【问题讨论】:

    标签: objective-c memory-management three20


    【解决方案1】:

    Sending a message to nil 在 Objective-C 中有效。向释放的对象发送消息不是。

    向已释放的对象发送消息:

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

    向 nil 发送消息:

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

    在对象被释放后将 nil 分配给变量是有争议的,因为它可以防止您意识到某些地方是错误的。镇静外星人的例子:

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

    由于 controlCenter 已被释放,此代码将崩溃。因此,该缺陷将被及早发现并修复。

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

    此代码会将 0.0 分配给 timeLeft,这似乎是一个有效的等待时间,即使 controlCenter 为 nil。


    对上述内容持保留态度,因为如果您正在编写一个 Objective-C 应用程序,您可能更关心通过避免崩溃而不是摧毁城市来让您的用户满意。如果后者是一个问题,您可能应该使用像 Ada 这样的类型安全语言。

    【讨论】:

    • 我认为是这样,这是某种最佳实践!
    • “有效”是指“不会在这个特定点崩溃”。它不会“做某事”(顾名思义),也许它应该是[obj wontDoAnything];?
    • @Sedate Alien:就未调用的方法而言,它不会做任何事情,但如果您选择使用它,它会给您一个有效的返回值(0、NO 等) .
    • @titaniumdecoy:它会给你一个 a 返回值,不一定是有效的。也许NO 应该只在采取某些操作后才返回,等等。NSZombieEnabled 呢?取消引用意味着它对您的调试没有帮助。
    • @Sedate Alien:你是对的,取消引用会使调试变得更加困难,这就是为什么我没有说这是一个好主意。然而,向 nil 发送消息将给你一个有效的、可预测的返回值;请参阅我帖子中的链接。
    【解决方案2】:

    我认为使用这些“安全版本”变体是一个明显糟糕的想法。

    您的应用程序将以静默和神秘的方式失败,因为传递给 nil 的消息不会引发任何警告。最好不要取消您的参考资料并利用NSZombieEnabled 提供的所有内容。

    【讨论】:

    • 或....#define TT_RELEASE_UNSAFELY(__POINTER) { [__POINTER release]; __POINTER = (id)0x42; }
    • 我认为我们可以在使用对象之前检查它是否等于nil。
    【解决方案3】:

    唯一的区别是TT_RELEASE_SAFELY在释放后将指针设置为nil,所以在释放后不会使用引用。该模式是一个很好的模式,TT_RELEASE_SAFELY 宏使其更易于实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      • 2016-03-01
      • 2011-08-30
      相关资源
      最近更新 更多