Безопасно ли автоматически высвобождать объекты внутри NSOperation? - PullRequest
3 голосов
/ 18 января 2011

Я выполняю операции типа NSInvocationOperation в NSOperationQueue, и мне было интересно, безопасно ли выполнять автоматическое высвобождение объектов - то есть гарантируется ли, что поток, запущенный для каждой операции, имеет свой собственный пул автоматического выпуска.Я не нашел никаких пулов автоматического выпуска документации для операций - чтение документов 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. Можно ли предположить, что этот объект вызовет release для всех моих автоматически выпущенных объектов после завершения операции?

1 Ответ

4 голосов
/ 18 января 2011

Я написал небольшую программу для проверки того, создаст ли NSInvocationOperation пул автоматического освобождения для операции:

#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" приведет к выполнению -performSomeTask: через NSInvocationOperation onдругая тема.В результате получается:

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

Как мы видим, есть экземпляры NSInvocation и NSSet, которые просачиваются , но автоматически высвобождаемая строка в -performSomeTask: не протекает , следовательно, для этой операции вызова был создан пул автоматического выпуска.

Я думаю, можно с уверенностью предположить, что NSInvocationOperation (и, вероятно, все подклассы NSOperation в каркасах Apple) создают свои собственные пулы автоматического выпуска, как иРуководство по программированию параллелизма предлагает для пользовательских NSOperation подклассы.

...