多线程iPhone应用程序因[NSAutoreleasePool release]崩溃

多线程iPhone应用程序因[NSAutoreleasePool release]崩溃,iphone,objective-c,memory-management,autorelease,retain,Iphone,Objective C,Memory Management,Autorelease,Retain,我在一个多线程iPhone应用程序中遇到了一个与内存管理相关的问题。 假设我们有一个方法,它是在主UI线程之外的单独线程中调用的: - (BOOL)fetchAtIndex:(NSUInteger)index { NSURL *theURL = [NSURL URLWithString:[queryURLs objectAtIndex:index]]; // Pay attention to this line: NSData *theData = [[NetworkHe

我在一个多线程iPhone应用程序中遇到了一个与内存管理相关的问题。 假设我们有一个方法,它是在主UI线程之外的单独线程中调用的:

- (BOOL)fetchAtIndex:(NSUInteger)index
{
    NSURL *theURL = [NSURL URLWithString:[queryURLs objectAtIndex:index]];
    // Pay attention to this line:
    NSData *theData = [[NetworkHelper fetchFromNetwork:theURL] retain];

    // Some code here...

    // Now what should I do before returning result?
    //[theData release]; ??
    //[theData autorelease]; ??
    return YES;
}
如您所见,我保留了从网络运营中获得的
NSData
。问题是:为什么我不应该在我的方法结束时释放(或自动释放)它? 我让它工作的唯一方法是先使用
retain
,然后什么都不使用。如果我使用任何其他组合(完全不使用;
retain
然后
release
autorelease
),当我释放线程的
NSAutoreleasePool
时,我的程序会在
EXC\u BAD\u ACCESS
下崩溃。 我错过了什么

仅供参考,以下是线程的主要代码:

- (void)threadedDataFetching;
{
    // Create an autorelease pool for this thread
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // Reload data in separate thread
    [self fetchAtIndex:0];

    // Signal the main thread that fetching is finished
    [self performSelectorOnMainThread:@selector(finishedFetchingAll) withObject:nil waitUntilDone:NO];

    // Release all objects in the autorelease pool
    [pool release]; // This line causes EXC_BAD_ACCESS
}

谢谢你的帮助

您不得发布您自己未保留的内容(使用
retain
或隐式使用方法:
init
new
copy

如果您保留了来自
fetchFromNetwork
的结果,则必须将其释放。
release
autorelease
都应该工作(在
release
之后不要触摸对象,在
release
之后,最安全的做法是将字段/变量设置为
nil

如果您不保留数据,那么您甚至不需要保留它<代码>[NetworkHelper fetchFromNetwork]应返回自动删除的对象。fetchFromNetwork的主体可以如下所示:

NSData *data = [[NSData alloc] init];
// stuff happens
return [data autorelease];


如果有疑问,请在泄漏端出错,并通过“泄漏”工具或运行应用程序。

您在一个单独的线程上这一事实可能与此无关。内存管理是一样的,您应该平衡NSData的保留/释放,就像这是主线程一样。您在耗尽自动释放池时崩溃的事实表明,您可能对此处未显示的数据做了一些处理(这似乎很明显,因为所示的代码不是很有用)。您如何处理需要其他人保留的数据?

正如其他人所指出的,在本例中,它是多线程的,这实际上并不相关。值得一读的是苹果公司生产的产品

粗略地说,任何您自己显式地[[Foo alloc]init]的对象,您都应该负责清理。如果要从方法返回此值,还需要自动释放它

从调用者处获得的任何不以initWith开头的对象(如[Foo emptyFoo]),调用者有责任拥有资源(即自动释放资源)


如果传递了一个对象,并希望将其保留在方法调用之外(即将其保存到实例字段),则必须保留该对象。完成后,通常在析构函数中释放它。如果您使用的是Objective C属性,那么将其定义为@retain将自动启动此行为;在析构函数中,您可以将属性设置为nil。

谢谢。事实上,fetchFromNetwork就像您的第二个代码示例:NSData*data=[otherObject dataFromOtherObject]。。。返回[数据自动释放];//这里错了!这就是为什么我必须在我的客户代码中保留它。我删除了错误的-autorelease调用,然后在客户端删除了-retain代码,现在一切都好了。谢谢你是对的,正如我在另一条评论中所写的,fetchFromNetwork正在自动删除NSData对象,因此我必须将其保留在代码中,这样它才能工作,但错误部分在fetchFromNetwork方法中。谢谢
NSData *data = [otherObject dataFromOtherObject];
// stuff happens
return data; // don't (auto)release, since you haven't retained