【问题标题】:when are objects released in objective-C program什么时候在 Objective-C 程序中释放对象
【发布时间】:2014-12-26 00:26:05
【问题描述】:

我正在使用 Big Nerd Ranch 指南来开始使用 Objective C。我对第 20 章中谈到的项目有一个问题。在较高的层次上,该项目执行以下操作

  1. 创建 3 个类 Person、Employee(从 person 继承)和 Assets(Employee 有一个指向 Assets 对象的实例变量)

  2. 然后它会创建 2 个 NSMUtableARrays

    • 数组 1:employees:Employee 对象数组(一些指向 0 资产对象,一些指向 1,一些指向 2 个资产对象)
    • Array 2: allAssets: Array os Asset 对象(每个创建的 Asset 对象一个条目)
  3. 随后,employees 数组中的一个对象被释放。这会导致此 Employee 对象被释放,但链接到 Employee 对象的资产对象并没有,因为 allAssets 数组拥有它

  4. 之后,我在 main 中的 return 0 之前放置了一个 sleep (60)

我看到如果 sleep(60) 在 @autoreleasepool{} 之后,那么所有对象都会在 1 分钟的睡眠发生之前被释放

但是如果 sleep(60) 发生在右大括号之前,那么所有对象都会在 1 分钟的 sleep 发生后被解除分配

为什么会这样?我认为只有在返回发生后自动释放才会启动?为什么在我将睡眠放在@autorelease{}之外的情况下它会在返回之前发生,它只是一个编译器优化,它认识到此时不再需要对象,因为剩下的唯一一行是sleep()?

我已将项目上传到

https://github.com/smartiothome/BMI

【问题讨论】:

    标签: objective-c memory-management autorelease


    【解决方案1】:

    查看 sleep() documentation:“sleep 命令暂停执行至少几秒钟。”

    在睡眠期间基本上什么都不会发生,这就是为什么它永远不应该在发布程序中使用。

    在程序退出时也这样做是未定义的。无论应用程序是否释放内存,系统都会回收所有内存,因此应用程序可能决定在终止时不打扰释放任何内容。另外:操作系统内核所做的几件事之一是处理资源,将它们作为请求提供给应用程序,并确保在应用程序正常终止或崩溃时回收所有资源。

    建议您根据应用关闭重新格式化问题,并据此打开一个新问题。

    【讨论】:

      【解决方案2】:

      当控制到达@autorelease 池的右括号时,即当前池被告知drain,这会导致您的对象被释放。您的睡眠电话延迟了drain

      为了更好地了解发生了什么,我建议您在他们添加新的@ 语法之前先看看NSAutoreleasePool 是如何工作的。这基本上就是幕后发生的事情。

      【讨论】:

      • 请注意,应用程序终止是一种特殊情况,自动释放池可能会或不会被耗尽。
      • 谢谢,尼克,这很有用。 Zaph,您能否详细说明“应用程序终止”是一种特殊情况。这是否意味着如果应用程序意外终止,在某些情况下会导致系统中留下一些“僵尸”内存(并且重新启动是清除所有内容的唯一选择)?这会不会导致iOS设备在使用一定量后会变得很慢?
      • 当应用程序以任何方式或路径退出时,操作系统将回收所有资源,包括应用程序获得的所有内存。不会有记忆丢失或僵尸。应用程序获取的所有内存由操作系统提供,因此它知道要回收的所有内存。这是操作系统内核的主要功能之一。顺便说一句:“资源”不仅仅是内存,它包括打开的文件、流、通信、任何有限的资源。
      • 如果您有兴趣,可以学习几本好书或可以参加大学课程,非官方审计是免费的——我的意思是非官方的,只是参加,不要注册,研究生课程不要扮演任何角色,我从未被要求离开,我参加过只有 8 名学生的课程。
      • 谢谢,扎夫。您推荐哪些书籍/课程?
      【解决方案3】:

      为什么会这样?我以为自动释放只会在 发生退货?

      当你autorelease一个对象时,当当前@autoreleasepool块(运行时调用堆栈中最里面的封闭@autoreleasepool块)结束时,它将是released。

      如果您在同一函数中的autorelease 周围没有@autoreleasepool 块,则“当前@autoreleasepool 块”位于调用框架更上方的调用函数中,因此会发生release从当前函数返回后。

      但是,在这种情况下,您在同一函数中的 autorelease 周围确实有一个 @autoreleasepool 块,因此 release 出现在该 @autoreleasepool 块的末尾。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-17
        • 2010-12-22
        相关资源
        最近更新 更多