无法访问的对象在无法访问后无法安全收集?

问题描述:

我在C++数据结构中存储了一些Obj-C对象。由于我的垃圾收集下运行,我的对象只能通过C++结构可到达,我打电话CFRetain()以root每个对象添加到结构,以确保它们不会过早地收集:无法访问的对象在无法访问后无法安全收集?

- (void) doSomethingFancyWithObjects:(NSArray*)array 
{ 
    std::list<NSObject*> list; 

    for (NSObject* obj in array) 
    { 
     id copyAddedToList = [obj copy]; 
     list.push_back(copyAddedToList); 
     CFRetain(copyAddedToList); // otherwise list.back() becomes unreachable... 
    } 

    // ... // 

    BOOST_FOREACH(NSObject* obj, list) 
    { 
     CFRelease(obj); 
    } 
} 

是否有必要这样做?实际上GC有可能在它们变得无法访问的方法中启动并收集无法访问的对象? GC是否可以在任何时间收集,或只在特定的时间收集,如运行循环结束?还没有设法找到这方面的相关文件。

我发现了一些信息在这里:

Garbage Collection Programming Guide

在一个标准的应用,可可自动在活动周期该集合可适当一个合适的点提示。如果内存负载超过阈值,收集器将启动收集。通常这应该足以提供良好的性能。然而,有时候,您可能会向收集器提供一个提示,说明收集可能是有保证的 - 例如,在创建大量临时对象的循环之后。您可以使用NSGarbageCollector方法collectIfNeeded来完成此操作。

这似乎表明垃圾收集器不会在函数中间(或者从另一个线程同时发生)奇迹般地运行,而只是在事件周期的某个地方运行。

你是对的,不过,在总体上保持在C对象++,如果你不希望他们是从下你收集了垃圾如该文件中还指出很重要:

一般来说,C++代码应该保持不变:您可以假定从标准malloc区域分配内存。如果您需要确保Objective-C对象的使用寿命,则应该使用CFRetain而不是retain。

EDIT

糟糕,我发现了参考的这种更illuminating part

集电极是包括请求和需求的驱动。 Cocoa实现在适当的时候发出请求。您也可以编程方式请求考虑垃圾回收周期,并且如果超过了内存阈值,则会自动运行集合。

收集器在应用程序中的其自己的线程上运行。

正如Jeremy指出的那样,即使您的函数位于主线程中,垃圾收集器也可以在函数的中间运行。

+0

好的地方,没有注意到你引用的第一段。但是,苹果仍然使用“事件循环”来引用主线程的运行循环,所以如果这就是他们的意思,我只能在主线程上运行时保证这种保证(不幸的是,我不是。 ..) – 2011-05-02 19:16:32

+0

哦,你的函数在另一个线程中运行?看起来你应该这样做CFRetain。与所有其他花哨的东西相比,这可能不是什么大事! – 2011-05-03 01:29:27

+1

垃圾收集器在其自己的线程中运行,只要感觉需要GC就会运行。你不能认为它没有在任何一个特定的功能中运行。 – JeremyP 2011-05-09 15:06:31

由于您的代码中发布的一切都发生在doSomethingFancyWithObjects:的范围内,因此您不需要CFRetain/CFRelease对,因为您并未从堆栈中的array中删除对象并因此生根。

编辑

OK,我没有正确读取编码 - 对象被复制。

首先,我会质疑需要复制。如果您正在修改列表中的对象,为什么?最后他们被抛弃。

其次,你实际上有一个竞争条件。垃圾收集器可能在list.push_back([obj copy]);CFRetain(list.back());之间,然后std::list中的对象指针将悬空。你应该这样做:

NSObject* theCopy = [obj copy]; 
CFRetain(theCopy); 
list.push_back(theCopy); 
+0

列表中的对象与数组中的对象不同(它被复制出来),因此它不是通过数组生成的。 – 2011-05-09 15:53:34

+0

@Chris:doh!... – JeremyP 2011-05-09 15:56:13

+0

@Chris:添加了一些进一步的评论。特别是你的代码有竞争条件。 – JeremyP 2011-05-09 16:03:45