2016-12-28 3 views
2

다음은 ARC를 사용하는 OS X 용 Objective-C 프로그램입니다. cc -fobjc-arc -o objc_arc_test objc_arc_test.m 등으로 빌드 할 수 있습니다. alloc/init을 사용하는 두 쌍과 factory 함수를 사용하는 두 쌍의 객체 두 개를 생성합니다 (pre-ARC 코드에 autorelease을 사용). 모든 자동 해제 풀 외부에 init 및 dealloc 메시지를 인쇄합니다. 간다.왜 이러한 ARC 개체가 일관성없이 동작합니까?

#import <Foundation/NSObject.h> 
#include <stdio.h> 

#if !__has_feature(objc_arc) 
#error 
#endif 

@interface TestClass:NSObject { 
    int value; 
} 
-(TestClass *)initWithValue:(int)value; 
-(void)dealloc; 
+(TestClass *)testClassWithValue:(int)value; 
@end 

@implementation TestClass 
-(TestClass *)initWithValue:(int)value_ { 
    if((self=[super init])) 
     self->value=value_; 

    printf("init: self=%p value=%d\n",self,self->value); 
    return self; 
} 

-(void)dealloc { 
    printf("dealloc: self=%p value=%d\n",self,self->value); 
} 

+(TestClass *)testClassWithValue:(int)value { 
    return [[TestClass alloc] initWithValue:value]; 
} 

@end 

static void f() { 
    TestClass *c5=[TestClass testClassWithValue:5]; 
    TestClass *c6=[[TestClass alloc] initWithValue:6]; 
} 

static void f2() { 
    TestClass *c7=[TestClass testClassWithValue:7]; 
    TestClass *c8=[[TestClass alloc] initWithValue:8]; 
} 

int main() { 
    f(); 
    f2(); 
} 

이 나는, 오토 릴리즈 풀의 부족으로 인하여, ARC는 ALLOC을 보장 + init'd 객체가 파괴되고 있기 때문에,이 4 개체 및 할당 해제 메시지를 초기화 메시지를받을 것입니다 예상했던 다른 것들은 그대로 두라.

는하지만 제가 대신 얻을 것은 3 4 개 개체의 초기화 메시지 및 할당 해제의 메시지입니다 :

init: self=0x7fea20500690 value=5 
init: self=0x7fea205006f0 value=6 
dealloc: self=0x7fea205006f0 value=6 
init: self=0x7fea205006f0 value=7 
init: self=0x7fea20500700 value=8 
dealloc: self=0x7fea20500700 value=8 
dealloc: self=0x7fea205006f0 value=7 

나는이 문제를 이해하지 않는다! 나는 값 = 5와 값 = 7 개체가 똑같이 행동 할 것으로 기대한다.

왜 이렇게 했습니까?

(OS X 10.11.6, 엑스 코드 8-Apple LLVM version 8.0.0 (clang-800.0.38), Target: x86_64-apple-darwin15.6.0, Thread model: posix)

답변

4

내가 OS X 10.9, 당신은하지 않더라도 자동으로 최상위 수준에 만든 오토 릴리즈 풀이 생각 때문에 하나 (이 autorelease 수영장, 그냥 누출 "경고없이 역사적인"개체 autoreleased 없애.

그렇다고해서이 상황과 관련이 없습니다. ARC는 어떤 것이 자동으로 릴리즈 될 것이라고 약속하지 않습니다. 나중에 객체를 사용하지 않는다는 것을 증명할 수있을 때 명시 적 릴리스를 사용하는 것은 무료입니다. ARC는 강력한 참조가있는 객체가 파괴되지 않도록하고 강력한 참조가없는 객체가 파괴되도록 보장해야합니다. Autoreleasepool은 ARC가 자유 재량으로 사용하거나 사용하지 않는 구현 세부 사항입니다. 최적화로서 ARC는 과거에 수동으로 사용했던 장소에서 자동 풀 풀을 피하는 경우가 종종 있습니다.

dealloc은 실제로 약속 된 적이 없습니다. 이 프로그램은 실행하지 않아도 자유롭게 종료 할 수 있습니다 (ObjC 프로그램이 C++ 프로그램보다 훨씬 빠르게 종료 될 수있는 방대한 최적화입니다). 이 경우에는 발생하지만 dealloc을 실행하거나 실행하지 않는 것이 좋을 것입니다.