2011-01-18 3 views
3

NSOperationQueue에서 NSInvocationOperation 유형의 작업을 실행하고 개체를 자동 저장하는 것이 안전한지 궁금해졌습니다. 즉, 각 작업에 대해 시작된 스레드가 자체 autorelease 풀을 가지고 있음이 보장되는 경우입니다.NSOperation 내부의 객체를 자동으로 내 보내면 안전합니까?

작업용 문서 자동 풀을 찾지 못했습니다. Apple의 문서를 읽으면 실제로 자동 복구 풀을 정의해야한다고 제안합니다.

그러나 1) 기기에서 누출이 발견되지 않습니다. 적어도 작동 중에 자체 자동 풀 풀을 할당 할 때만 큼은 아닙니다. 디버거에서 찾고

2)이 스택 트레이스 볼 수 있습니다 : 그래서 그것은 CFAutoreleasePool이있는 것처럼 보이는

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

를 - 그것은 내 모든 오토 릴리즈 객체 때 일에 출시 호출 할이 객체를 가정하는 안전한가요 작업이 완료 되었습니까?

답변

4

나는 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"을 전달하지 않고 프로그램을 실행하면 다른 스레드의 NSInvocationOperation을 통해 -performSomeTask:이 실행됩니다. 결과 출력은 :

우리가 알 수 있듯이, 누출되지만 -performSomeTask:에서 오토 릴리즈 문자열 누출되지 NSInvocationNSSet의 인스턴스가
$ ./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 

, 따라서 오토 릴리즈 풀 그 호출 동작 작성된 .

가 나는 NSInvocationOperation (애플의 프레임 워크와 probally 모든 NSOperation 서브 클래스)는 동시성 프로그래밍 가이드는 사용자 정의 NSOperation 서브 클래스 제안처럼, 자신의 오토 릴리즈 풀을 만들 수 있다고 가정하는 것이 안전합니다 생각합니다.

+0

iOS 3.x에서 테스트 했습니까? 여기에 설명 된대로 GCD 구현 세부 사항이 될 수 있습니다. http://stackoverflow.com/questions/4141123/do-you-need-to-create-an-nsautoreleasepool-within-a-block-in-gcd – Danra

+0

@Danra AFAICT NSOperationQueue는 GCD를 사용하지 않습니다. 또한 위의 코드를'[op start]'를 통해 동 기적으로 실행하도록 변경하면 문자열이 누수되었음을 나타내는 메시지가 표시되지 않습니다. 즉, NSInvocationOperation이 조작을위한 자동 해제 풀을 생성합니다. –

+0

@Danra Mac OS 10.6.6에서만이 동작을 테스트했습니다. –

관련 문제