2010-12-31 6 views
4

목표 - C에서 변수를 해제하는 올바른 방법 :난에 목표 - C를 다음과 같이 변수를 선언하는 아주 쉬운 방법이 알고

NSArray* myArray; 

@property(retain) NSArray* myArray; 

@synthesize myArray; 

당신은 세터 모두로 self.myArray를 사용할 수있는이 방법 변수를 유지하면서 게터를 가져옵니다. 그러나 이것은 또한 dealloc을 사용하는 것을 피하는 또 하나의 일을 할 수있게 해줍니다. 내가 이해하는 한,이 두 라인은 동일합니다 :

self.myArray = nil; 
[myArray release]; 

제 질문은 어느 것이 좋습니다? 그 중 하나가 작동하고 다른 하나는 작동하지 않는 경우가 있습니까?

편집 : 미안 해요, 난 당신이 객체 인 인스턴스 변수가 때마다, 당신은의 dealloc 메소드에서 해제해야

답변

3

하단 업데이트.

합성 속성을 사용하여 작업 할 때 가장 적합한 방법은 속성을 nil로 설정하는 것입니다. 이것이 내가 "최선의 방법"이라고 말한 이유는 그것이 재산 선언에 내포 된 모든 계약이 충족되도록하는 것입니다. 예를 들어, 속성이 원자 적으로 선언 된 경우 (즉, 비 원자로 명시 적으로 선언하지 않는 한) dealloc에서이 속성을 설정 해제하는 작업이 동일한 원자 적 보장으로 수행된다는 것을 보장하는 유일한 방법은 다음을 사용하여 nil로 설정하는 것입니다. dealloc의 property입니다. 이것은 또한 객체의 키 - 값 관측과 관련하여 올바르게 동작 함을 의미합니다. 특히 코코아 바인딩을 사용하는 경우 중요 할 수 있습니다.

해당 속성이없는 (아마도 개인적인) 인스턴스 변수에 대한 고유 한 메모리 관리를 수행 할 때 몇 가지 숙어가 있습니다.

- (void)dealloc 
{ 
    [myArray release]; 

    [super dealloc]; 
} 

이이 출시 될 IVAR에 유지하게됩니다 만, 다른 사람이 언급 한 바와 같이, 지금은 잠재적으로 부실 포인터를 떠나 : 간단한, 그러나 가장 위험한, 단순히 그렇게처럼 바르를 해제하는 것입니다 할당이 해제 될 객체를 가리킬 수있는 부실 포인터 또는 유지되지 않은 포인터에 의해 잠재적으로 잠재적으로 오용 될 수 있습니다.

- (void)dealloc 
{ 
    [myArray release], myArray = nil; 

    [super dealloc]; 
} 

이보다 더욱 안전하고 현학적 인 경우, 이에 대한 관용구는 다음과 같습니다 : 다음 길을 따라 다른 답변에서 제안하는 관용구이다이 더

- (void)dealloc 
{ 
    id temp = myArray; 
    myArray = nil; 
    [temp release]; 

    [super dealloc]; 
} 

은의 읽기 부실의 가능성을 제한한다 포인터를 가리키는 객체를 놓기 전에 iVar를 지우면됩니다. 그러나 명령 순서 재 지정 가능성으로 인해 모든 아키텍처에서 오래된 읽기를 100 % 보장하지는 못합니다.

동시성 및 메모리 관리에 관해서는 더 많은 이야기가 있지만, 일반적으로 @synthesized 속성 설정 기가있는 경우에는 dealloc에서 사용해야합니다. 이렇게하면 @property의 동작을 변경하면 deprooc 동작이 @property 선언과 관련하여 자동으로 올바르게 수행됩니다.

중요 정보 : 원자 속성 사용! = 스레드 안전성. (실제로, 당신이 물으면 원자 성 물질은 낭비이지만 ...) 자세한 내용은 here을 참조하십시오.

UPDATE

이 최근 다시 upvoted있어, 나는 내가 속성을 유지 합성과 원자 보장 여기에 대해 말을 대기하고있는 동안 원래의 대답에 다른 내용이 그 자체로 가치가, 나는 이야기의 다른쪽에 말할 필요성을 느낀다. Dave DeLong은 주석에서이 점에 대해 언급했으나 주 응답에 세부 사항을 추가 할 가치가 있다고 생각했습니다.

원자 성 보장을 유지하는 유일한 방법은 설정자를 통해 속성을 nil으로 설정하는 것입니다. BUT 당신이 신경 쓰지 말아야 할 이유는 다음과 같습니다. 객체가 dealloc 인 경우 그 객체에 대한 실제 참조가 없어야 함을 의미합니다 (객체 그래프가 올바른 경우). 객체에 대한 실제 참조가 없으면 해당 객체를 지우는 작업의 원 자성 보장에 대해 아무도 염려하지 않을 수 있습니다.

나는 원래 대답에서 setter를 사용하는 이유로 dealloc에서 KVO를 언급했지만 Dave DeLong은 의견에서 KVO를 대위법으로 언급했습니다. 맞습니다. 여기에 이유가 있습니다 : 다시 한 번, 물체가 dealloc 일 경우 모든 KVO 관측자가 이미 제거 된 상태 여야합니다 (다시 말하면 살아있는 참조 물, KVO가 없어야 함). 실제로 이것이 사실이 아니라면, 여러분의 객체가 관측과 함께 사라 졌음을 알리는 콘솔 메시지를 볼 때까지 그리 길지 않을 것입니다. 한마디로

, 당신은 dealloc의 합성 세터들에게 자성 보장은 동일 할 수는 없지만, 그것은 결코 문제 (그것이 않는 경우와, 다른 뭔가가 고장.)

+0

응용 프로그램 자체에서 멀티 스레딩 프로그래밍을 수행하는 경우 이러한 예방 조치가 필요하다는 말입니까? 멀티 스레딩을하지 않으면 [myArray release]를 사용하는 것이 좋습니다. –

+0

요즘에는 키트에서 등 뒤에서 멀티 스레딩이 일어나지 않는지 100 % 확신 할 수 없습니다 (거의 항상 그렇습니다). 일반적으로 단일 스레드 응용 프로그램이 있다면 걱정할 필요가 없습니다. 그러나 계측기 CPU 샘플러/시간 프로파일 러 프로파일에서 'dealloc> setFoo :'를 본 적이 없다면 그 변화를 '조기 최적화'라고 할 수 있습니다. 그리고 솔직히, 만약 당신이 차이를 보게된다면, 당신은 뭔가 잘못하고있는 것입니다. – ipmcc

+0

좋아 ...하지만 그 변수에 @property (보유)가 있다면 답을 내포 했습니까? 나는 self.myVar = nil을 할 수 있는데, 변수를 할당 해제하고 그것을 nil로 설정하겠습니까? (두 번째 dealloc 상황과 동일) –

1

... 할당 해제되지, 해제 의미했다. 따라서 귀하의 경우에는 사용해야합니다.

- (void)dealloc 
{ 
    [myArray release], myArray = nil; 

    [super dealloc]; 
} 
4

절대로 절대 dealloc을 호출해서는 안됩니다 (매우 정교하지 않은 경우 제외).

dealloc 대신 [myArray release]을 호출하고 출시 된 프로세스가이 문제를 처리하도록해야합니다.

dealloc 메소드에서 사용자가 원하는 것보다 더 많은 정보를 보려면 here을보십시오.

+0

미안 해요, 난 의미를했다한다 [myArray release]를 작성하십시오. 하지만 실제로 self.myArray = nil과 동일합니까? –

+0

self.myArray = nil이 (가) 귀하의 케이스에서 릴리스를 호출합니다. 그러나 self.myArray = nil은 [self setMyArray : nil]과 같습니다. 따라서이 문제를 직접 무시하는 경우 올바른 작업을 수행해야합니다. – slycrel

+0

Instruments를 사용하여 응용 프로그램을 실행하려고 시도했지만 self.myArray = nil을 사용할 때 누출이없는 것 같습니다. 그 변수의 보유 속성을 합성했기 때문에 이것입니까? –

1

이론적으로 nil로 설정하면 ivar를 해제하는 것과 동일한 효과가 있어야합니다. 그러나 결코 dealloc 메서드를 직접 호출해서는 안됩니다. 의 dealloc 메서드에서 가끔 특히, 다윗 언급 한 관용구를 참조하십시오

[myArray release], myArray = nil; 

그 이유는 사람이 할당 해제가 완료되기 전에 출시 된 개체에 액세스 해보십시오 수있는 매우 가능성 경쟁 조건을 방지하는 것입니다. 속성을 nil에 할당하면 시도 된 액세스가 정상적으로 실패 할 수 있습니다.