首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在NSOperation中自动释放对象是否安全?

在NSOperation中自动释放对象是否安全?
EN

Stack Overflow用户
提问于 2011-01-18 21:56:01
回答 1查看 1.5K关注 0票数 3

我正在NSOperationQueue中运行NSInvocationOperation类型的操作,我想知道自动释放对象是否安全-也就是说,是否保证为每个操作启动的线程都有自己的自动释放池。

我没有找到任何用于操作的文档自动释放池-阅读苹果的文档实际上表明我确实需要定义我自己的自动释放池。

但是: 1)我在工具中看不到任何泄漏,至少不会比我在操作中分配自己的自动释放池时更多。

2)查看调试器,我可以看到堆栈跟踪:

代码语言:javascript
复制
#0  0x00fc3e82 in -[NSObject(NSObject) release] ()
#1  0x00faaa6c in CFRelease ()
#2  0x00fbf804 in __CFBasicHashDrain ()
#3  0x00faabcb in _CFRelease ()
#4  0x00fcfb8d in _CFAutoreleasePoolPop ()
#5  0x000edd0d in -[__NSOperationInternal start] ()
#6  0x000ed826 in ____startOperations_block_invoke_2 ()
#7  0x94358024 in _dispatch_call_block_and_release ()
#8  0x9434a2f2 in _dispatch_worker_thread2 ()
#9  0x94349d81 in _pthread_wqthread ()
#10 0x94349bc6 in start_wqthread ()

所以看起来好像有一个CFAutoreleasePool -当操作完成时,假设这个对象将在所有自动释放的对象上调用release,这样做安全吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-18 22:53:42

我已经写了一个小程序来测试NSInvocationOperation是否会为操作创建一个自动释放池:

代码语言:javascript
复制
#import <Foundation/Foundation.h>

@interface MyClass : NSObject
@end

@implementation MyClass
- (void)performSomeTask:(id)data
{
    NSString *s = [[[NSString alloc] initWithFormat:@"hey %@", data]
        autorelease];
    if ([[NSThread currentThread] isMainThread])
        NSLog(@"performSomeTask on the main thread!");
    else
        NSLog(@"performSomeTask NOT on the main thread!");

    NSLog(@"-- %@", s);
}
@end

int main(int argc, char *argv[]) {
  MyClass *c = [MyClass new];

  if (argc == 2 && strcmp(argv[1], "nop") == 0)
      [c performSomeTask:@"ho"];
  else {
      NSInvocationOperation *op = [[NSInvocationOperation alloc]
          initWithTarget:c
                selector:@selector(performSomeTask:)
                  object:@"howdy"];
      NSOperationQueue *queue  = [[NSOperationQueue alloc] init];
      [queue addOperation:op];
      [op waitUntilFinished];

      [op release];
      [queue release];
  }

  [c release];

  return 0;
}

它的工作原理如下:如果在命令行上传递了"nop“,它将直接在主线程上执行-performSomeTask:,而不使用自动释放池。结果输出为:

代码语言:javascript
复制
$ ./c nop
*** __NSAutoreleaseNoPool(): Object 0x10010cca0 of class NSCFString autoreleased with no pool in place - just leaking
performSomeTask on the main thread!
-- hey ho

-performSomeTask:中的自动释放字符串会导致泄漏。

在不传递"nop“的情况下运行程序将通过不同线程上的NSInvocationOperation执行-performSomeTask:。结果输出为:

代码语言:javascript
复制
$ ./c
*** __NSAutoreleaseNoPool(): Object 0x100105ec0 of class NSInvocation autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x100111300 of class NSCFSet autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x100111b60 of class NSCFSet autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x100105660 of class NSCFSet autoreleased with no pool in place - just leaking
performSomeTask NOT on the main thread!
-- hey howdy

正如我们所看到的,有NSInvocationNSSet的实例正在泄漏,但-performSomeTask:中的自动释放字符串没有泄漏,因此为该调用操作创建了一个自动释放池。

我认为可以安全地假设NSInvocationOperation (以及苹果框架中的所有NSOperation子类)创建自己的自动释放池,就像并发编程指南为自定义NSOperation子类所建议的那样。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4724876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档