在 NSOperation 中自动释放对象安全吗?

发布于 2024-10-13 01:48:17 字数 837 浏览 7 评论 0原文

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

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

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

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

#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 - 可以安全地假设该对象将在操作完成时对所有自动释放的对象调用释放吗?

I am running NSInvocationOperation-type operations in an NSOperationQueue and was wondering if it is safe to autorelease objects - That is, if it is guaranteed that the thread started for each operation has its own autorelease pool.

I didn't find any documentation autorelease pools for operations - Reading Apple's docs actually suggests I do need to define my own autorelease pool.

However:
1) I can't see any leaks in instruments, at least not more than when I allocate my own autorelease pool in the operation.

2) looking in the debugger I can see this stack trace:

#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 ()

So it looks as though there is a CFAutoreleasePool - Is it safe to assume this object will call release on all my autoreleased objects when the operation is complete?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

峩卟喜欢 2024-10-20 01:48:17

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

#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: 直接在主线程上,没有自动释放池。结果输出是:

$ ./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”的情况下运行程序将通过不同线程上的 NSInitationOperation 执行 -performSomeTask:。结果输出是:

$ ./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

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

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

I’ve written a small program to test whether NSInvocationOperation would create an autorelease pool for the operation:

#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;
}

It works as follows: if "nop" is passed on the command-line, it will execute -performSomeTask: directly, on the main thread, with no autorelease pool in place. The resulting output is:

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

The autoreleased string in -performSomeTask: causes a leak.

Running the program without passing "nop" will execute -performSomeTask: via an NSInvocationOperation on a different thread. The resulting output is:

$ ./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

As we can see, there are instances of NSInvocation and NSSet that are leaking but the autoreleased string in -performSomeTask: isn’t leaking, hence an autorelease pool was created for that invocation operation.

I think it’s safe to assume that NSInvocationOperation (and probally all NSOperation subclasses in Apple’s frameworks) create their own autorelease pools, just like the Concurrency Programming Guide suggests for custom NSOperation subclasses.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文