释放对象后分配'nil'的需要是啥

Posted

技术标签:

【中文标题】释放对象后分配\'nil\'的需要是啥【英文标题】:What is the need of assigning 'nil' after releasing an object释放对象后分配'nil'的需要是什么 【发布时间】:2012-02-14 11:35:30 【问题描述】:

我通常在使用后释放对象

[myObject release];

但我在一些在线教程中发现他们在释放对象后分配了 nil。喜欢

[myObject release];
myObject = nil;

需要吗?

【问题讨论】:

Why set object to nil after sending release message in Obj-C的可能重复 其他候选人:Set pointers to nil after releaseIs it necessary to set pointers to nil after releaseWhen to set object references to nilDifference between release and release, then set to nil 【参考方案1】:

关于是否有必要在发布后将指针设置为nil 是一个长期争论,但我认为这是一个好主意。

对象被释放后,你指向它的指针仍然指向同一个地方。如果您的版本已将保留计数设为 0,则该对象将被释放。如果您随后尝试向已释放的对象发送消息,您将收到 EXC_BAD_ACCESS 错误。但是,在指针设置为 nil 后向指针发送消息不会出错 - 它不会做任何事情。

论点的另一面是,如果您正在向一个已释放的对象发送消息,最好了解它并修复您的代码以确保它不会发生。

两个阵营都有聪明人。

【讨论】:

【参考方案2】:

不,这不是严格要求的。 如果您的代码结构良好,则无需强制 myObject 等于 nil。

但这可能是一个好习惯:release 不会立即销毁对象,只是减少 retain 计数。因此,即使您调用 release,对象仍会存在一段时间,如果您尝试向其发送消息,则会产生问题。

使用myObject = nil; 可消除此问题,因为即使您向myObject 发送消息,实际上也不会发生任何事情。

【讨论】:

我只能添加这个great blog post by Jeff Lamarche。读起来很有趣。 如果在发布时保留计数将变为零,则该对象将被销毁。但是内存没有被清除,所以它可能看起来仍然存在。只有指针值设置为零。保护措施是,如果代码的另一部分通过指针引用并且指针为零,则不会发生任何不良情况,请注意,这涵盖了代码中的错误!。还有一种可能,赋值(id)0x42,这样如果有通过指针的acede错误会立即crash,然后代码就可以修复了。【参考方案3】:

这不是必需的,但主要是样式问题。在发布后分配nil 可确保您不会意外再次使用已发布的引用(这可能会也可能不会导致崩溃)。简单地在引用上调用release 可能会使底层内存消失。但是,指针仍将指向(现在可能无效)地址,并且使用该指针的后续方法调用的结果是未定义的。

【讨论】:

【参考方案4】:

不,这不是必需的。

这是一件安全的事情。如果你有

[myObject release];

然后你在其他地方做

[myObject doSomething];

那么你就会遇到问题。

如果你有

[myObject release];
myObject = nil;

然后你在其他地方做

[myObject doSomething];

然后什么都不会发生,因为你调用的是一个 nil 对象。因此,您的应用程序不会只是堆成一大堆。或者,如果您在代码中还有其他地方

[myObject release];

然后它将在一个 nil 对象上释放,因此不会过度释放。

显然你应该避免调用你已经释放的对象!

【讨论】:

【参考方案5】:

我总是设置为零。

Apple 自己有时(记录在案)会检查 nil。

示例;

如果您设置了navigationItem.titleView,如果您想恢复使用navigationItem.title,则需要将其设置回nil,否则您的标题将不会显示。

Apple 文档中有很多关于这种“零检查”的引用。

参考;

https://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationItem_Class/Reference/UINavigationItem.html

Restoring navigationItem.title after removing navigationItem.titleView

【讨论】:

【参考方案6】:

不是真的,但最好用它来防止错误......

如果您在代码 myObject 发布时在某处调用它,它会给您一个严重错误, 但如果它被设置为 nil,则错误可能会被绕过

如果你尝试:

myObject.someProperty = 1;

if (myObject) ...

而您刚刚发布了 myObject,它可能会使您的应用崩溃...

【讨论】:

【参考方案7】:

这不是必需的,但它通常被认为在所有环境中都是好的做法,但在-dealloc 方法中通常认为它是不必要的。

释放后将对象指针设置为 nil 的常见原因是,Objective-C 方法调度程序不会尝试向 nil 对象发送消息,这意味着您以后不小心使用该对象是安全的.

【讨论】:

【参考方案8】:

在释放一个 abject 但不分配 NULL 后,它保留地址但内容被释放。所以现在它没有指向任何有效的内存位置。因此 ptr 现在是悬空指针,它可能有一个地址但没有指向任何有效的内存位置。 因此最好在释放分配的内存后分配 NULL,如下所示

ptr=NULL;

这样就解决了悬空问题。

【讨论】:

【参考方案9】:

我建议采用混合方法。让我们看看典型的应用需求:

    我们希望最大限度地减少生产中的应用程序崩溃 我们希望在测试时发现访问可能释放的内存等问题

一个好的解决方案是有条件地分配给:

    发布版本中为零 调试中故意错误的指针(例如 0x20)。

这为生产构建带来了稳定性,但在调试模式下,任何访问变量的尝试都会显式地使应用程序崩溃。请注意,在对象上调用 release 并不能保证对象内存将被删除,因此需要显式设置为坏指针。

#ifdef DEBUG
    #define RELEASE(obj) [(obj) release]; (obj) = (id)0x20;
#else
    #define RELEASE(obj) [(obj) release]; (obj) = nil;
#endif

【讨论】:

【参考方案10】:

在几年前我参加的一次 Apple 技术讲座中,Apple 工程师讨论了一些必须分配给 nil 的实例,但除了讨论的实例中的 dealloc 内部之外,我不记得其他细节.只要说你永远不必这样做是不正确的,或者这样做是不好的做法就足够了。有时你必须这样做。但大多数时候你不必这样做。抱歉我的记忆不太清楚。

【讨论】:

以上是关于释放对象后分配'nil'的需要是啥的主要内容,如果未能解决你的问题,请参考以下文章

自动释放并分配给 nil

为啥在释放对象后使用'nil'

当对象在运行时释放时,确保nil或null值

dll里面分配的空间一定要在dll里面释放吗?

在 C 中释放内存需要啥?

linux采用啥方法实现内存的分配和释放