2

我在多线程 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然后releaseautorelease),EXC_BAD_ACCESS当我释放线程的NSAutoreleasePool. 我错过了什么?

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

- (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
}

谢谢你的帮助!

4

3 回答 3

3

你不能释放你自己没有保留的东西(使用retain或隐含地使用带有: initnewcopy以他们的名义的方法)。

如果您保留来自 的结果fetchFromNetwork,那么您必须释放它。两者都release应该autorelease工作(不要在之后触摸对象release,将字段/变量设置为nilafter是最安全的release)。

如果您不保留数据,那么您甚至不需要保留它。[NetworkHelper fetchFromNetwork]应该返回自动释放的对象。的主体fetchFromNetwork可能如下所示:

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

或者

NSData *data = [otherObject dataFromOtherObject];
// stuff happens
return data; // don't (auto)release, since you haven't retained

如果有疑问,请在泄漏方面犯错并通过“泄漏”仪器或LLVM 检查器运行应用程序。

于 2009-07-27T20:40:15.367 回答
0

正如其他人所指出的那样,在这种情况下它实际上是多线程的并不相关。值得一读 Apple 制定的Objective C 内存管理指南

粗略地说,任何你自己明确地 [[Foo alloc] init] 的对象,你都应该负责清理。如果你从一个方法中返回这个值,你也需要自动释放它。

您从调用者那里获得的任何不以 initWith 开头的对象(例如 [Foo emptyFoo])都是调用者负责拥有该资源(即自动释放它)。

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

于 2009-07-28T08:55:16.603 回答
0

您在单独的线程上的事实可能与此处无关。内存管理是相同的,您应该平衡 NSData 的保留/释放,就好像这是主线程一样。您在排空自动释放池时崩溃的事实表明您可能已经对未在此处显示的数据进行了某些操作(这似乎很明显,因为显示的代码不是很有用)。你在用需要其他人保留它的数据做什么?

于 2009-07-27T20:52:35.670 回答