【问题标题】:Who is responsible for releasing objects in an array when copying?复制时谁负责释放数组中的对象?
【发布时间】:2010-11-08 10:20:22
【问题描述】:

在 Objective-C 中,如果使用 mutableCopy 将 array1 复制到 array2,并且假设代码在 main() 中完成,那么谁负责释放数组中包含的对象?是main()还是array2?

【问题讨论】:

    标签: objective-c cocoa memory-management nsarray


    【解决方案1】:

    我认为以前的答案没有抓住重点,否则提问者很不清楚。实际问题不是在谈论任何一个数组,而是在谈论数组内容:

    谁负责释放数组中包含的对象?是main()还是array2?

    array1array2 都负责释放对象。

    来自NSArray documentation

    “数组维护对其内容的强引用——在托管内存环境中,每个对象在其 id 被添加到数组之前都会收到一条保留消息,当它从数组中删除时或在数组中删除时会收到一条释放消息被释放。”

    首先,每个对象都由 NSArray array1 保留。当您通过-mutableCopy 创建array2 时,您会得到一个指向相同对象的NSMutableArray,并再次保留它们中的每一个。如果此时你要释放array1,当它的dealloc 方法被调用时,它会释放它包含的每个对象。但是,array2 保留了它们,因此对象不会被销毁 - 只有当它们的保留计数达到 0 时,如果 array2 被销毁并且没有其他人保留任何对象(或者当它们被删除时,就会发生这种情况来自array2)。

    由于集合类(数组、集合、字典等)处理保留和释放它们的内容,您只需担心保留或释放集合本身。由于您使用了-mutableCopy,请记住您已经隐式保留了array2,因此您应该在完成后释放它。

    【讨论】:

    • 谢谢,我不知道副本很浅。 :)
    • 哈!不知道这样说就够了。很难衡量响应中所需的详细程度。 :-)
    【解决方案2】:

    我在 Obj-C 中引用 this guide 的内存管理。他有一个关于数组和字典的部分,摘录如下:

    数组、字典等通常会保留添加到其中的任何对象。 (在处理 3rd 方集合类型对象时,请始终检查文档以查看它们是否保留)。这意味着这些集合将取得对象的所有权,并且您不需要在添加之前保留。

    发帖的cmets也很有用

    【讨论】:

      【解决方案3】:

      将对象存储在数组中不会改变所有权职责。这是一个例子:

      int main(int argc, char *argv[])
      {
          // ...
      
          NSObject *obj1 = [[NSObject alloc] init]; // owned
          NSObject *obj2 = [[NSObject alloc] init]; // owned
          NSObject *obj3 = [[[NSObject alloc] init] autorelease]; // not owned
      
          NSMutableArray *array1 = [NSMutableArray arrayWithObjects: obj1, obj2, obj3, nil]; // not owned
          NSMutableArray *array2 = [array1 mutableCopy]; // owned
      
          // ...
      
          [array2 release];
          [obj2 release];
          [obj1 release];
      
          // ...
      }
      

      这段代码直接分配obj1obj2,所以它拥有它们并且必须释放它们,但是它自动释放obj3,所以它不必释放它们。同样的,它不拥有arrayWithObjects: 的结果,所以它不释放它,但它拥有mutableCopy 的结果,所以它必须释放它。存储在数组中的对象是无关紧要的——您只需要关心所有权。

      两个数组都保留对其内容的强引用,因此只要数组存在,obj1obj2obj3 就不会被释放 - 但这是 NSArray 合约的细节,它不会' 不会影响您管理对象或数组的所有权的方式。

      这些都是Cocoa's memory management conventions 的详细信息,而不是数组。

      【讨论】:

      • 感谢您花时间解释。 :)
      【解决方案4】:

      将可变数组绑定到不可变数组是没有意义的。 main() 将负责释放 array1。

      然而,根据我的经验,释放对象只会导致应用程序崩溃。 ObjC 非常擅长自动管理内存。即使运行了几个小时,我的 Cocoa 应用程序似乎也不需要比开始时更多的内存。

      【讨论】:

      • 释放对象可能会导致崩溃,因为您没有正确保留对象。建议某人忽略内存管理规则总是一个坏主意。无法释放对象只会在垃圾回收下不会泄漏,这总是不好的做法。
      • 另外,array1 和 array2 都不负责相互释放,但是可变数组与不可变数组“绑定”在一起,因为它们都包含相同的对象,至少一开始是这样。跨度>
      • 垃圾回收系统复杂。它试图在提供直接控制的同时为您做一些工作。这种混合方式的结果是有些对象自动释放,有些需要手动释放。但是根据我的经验,即使是那些没有自动释放的程序,如果它们被强制释放,它们也会使程序崩溃。我建议任何人在遵循时忽略任何导致程序崩溃的规则。正如我所说,我的 ObjC 应用程序忽略了垃圾收集,并且在运行几个小时后它们没有显示任何内存泄漏。实践高于原则。
      • 其实没那么复杂。您误解了 Obj-C 内存管理系统——垃圾收集与保留/释放/自动释放完全不同。诚然,您确实必须了解何时需要保留或释放对象,但只有少数情况需要记住。奇怪的是您没有看到泄漏的原因是(1)大多数 Cocoa 方法返回自动释放的对象,以及(2)您可能没有泄漏足够多的对象来真正注意到。我几乎可以保证,如果你忽略内存管理规则,你就会有泄漏。尝试在 Instruments 中运行以找到它们。 :-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多