2011-04-14 2 views
2

어제까지 내가 iPhones 메모리 관리를 이해했다고 생각했습니다. 그럼 여기 내 문제 : 나는 예를"self.variable = value"로 인스턴스 변수를 두 번 설정하면 메모리 누수가 발생합니까?

self.dicParams = dicValues; 

의의 ViewController의 할당 한 후, 다른 곳에서 설정하면 그것은 누출로 바뀝니다 ...

// .h file 
    @property(nonatomic, retain) NSMutableDictionary *dicParams; 
    @property(nonatomic, retain) NSMutableDictionary *dicReferences; 
    @property(nonatomic, retain) FtMonitorHandler *monitorHandler; 

// .m file 
@synthesize dicParams, dicReferences, monitorHandler; 

- (id)init { 
    self = [super init]; 

    if (self) { 
     self.dicParams = [[NSMutableDictionary alloc] init]; 
     self.dicReferences = [[NSMutableDictionary alloc] init]; 
     self.monitorHandler = [[FtMonitorHandlerService alloc] init]; 
    } 
    return self; 
} 


- (void)dealloc { 
    [monitorHandler release]; 
    [dicParams release]; 
    [dicReferences release]; 
    [super dealloc]; 
} 

인스턴스 변수를 설정하는 나의 이해 "self ... ..."는 현재 값이 "release"되고 "retain"으로 설정된다는 것입니다.

악기를 조금 사용해 보았습니다. 결과 :

내가 놓친 것이 있습니까? 그렇지 않으면 정상적으로 작동합니까?

수정 : 제안 된 변경 사항을 구현하려고했습니다. 내 변수가 GUI 요소가 아니기 때문에 오래 사용할 수 있습니다. (UIView의, UILabel의 등)

오토 릴리즈는

- (void)loadView { 
    [super loadView]; 
    // ... here is some other stuff ... 
    self.lblDeparture = [[[UILabel alloc] init] autorelease]; 
} 

- (void)viewDidUnload { 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    self.lblDeparture = nil; 
} 

- (void)dealloc { 
    [lblDeparture release]; 
    [super dealloc]; 
} 

내가 아주 확실하지 않다 경고 메모리 후 응용 프로그램 충돌이 발생할 것입니다,하지만 난 다음 줄은 진짜 문제가 있다고 가정 :

CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, INFO_VIEW_HEIGHT); 
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame]; 

[imageView addSubview:lblDeparture]; 
[lblDeparture release]; // is this correct? 

[self.view addSubview:imageView]; 
[imageView release]; 
+0

왜 self.yourObjects를 사용하는지, 동일한 클래스에 있으므로 self.yourObject를 호출하여 보유하지 않고 자기없이 시도 할 수 있습니다. – Ravin

+0

첫 번째 참조가 사라질 것이기 때문에 "variable = ..."변수를 두 번 할당하면 누수가 발생하지 않을까요? "self.variable ..."이 없다면 – user707342

+0

아니오 dicParams = [[NSMutableDictionary alloc] init]으로 시도해야한다고 말합니다. 대신 self.dicParams = [[NSMutableDictionary alloc] init]; . – Ravin

답변

4

초기화하는 경우 자동으로 해제해야합니다.

-(void)dontCreateAnotherLeak { 
    self.dicParams = [[[NSMutableDictionary alloc] init] autorelease]; 
    self.dicParams = nil; 
    self.dicParams = [[[NSMutableDictionary alloc] init] autorelease]; 
} 

편의상 액세서를 사용하는 것이 더 쉽습니다.

self.dicParams = [NSMutableDictionary dictionary]; 

당신이 직접 처리하고 싶다면. @synthesize dictParams의 맨 위에; 당신은 또한 당신 자신의 세터를 만들고 싶을 것이다.

-(void)setDictParams:(NSMutableDictionary*) newDictParams 
{ 
    if (dictParams != newDictParams) 
    { 
     [dictParams release]; 
     dictParams = [newDictParams retain]; 
    } 
} 

이것은 약간 간단합니다. 하지만 컴파일러는 당신은 당신이 자기를 참조하여 전화로 카운트가 이제 1

를하게 유지 propertyretain를 지정하는에 대한 인스턴스 변수를 설정하면 @property 태그

+1

좀 더 구체적으로 초기화하고 ALSO가 유지하는 설정 자로 전달할 때 자동 응답이 필요합니다 ... –

+0

'[NSMutableDictionary dictionary]'로 포장하십시오. –

+0

답장을 보내 주셔서 감사합니다. 나는 그것을 테스트했고 잘 동작했다. 비록 내가 autorelease없이 그것을 사용하고 내가 나중에 릴리스 – user707342

0

에 추가 된 보유 수정으로 생성 본질적으로 무엇을 "self.variable = value"와 마찬가지로 retain 카운트를 1 씩 증가 시키므로 총 보유 수는 2가됩니다.

이제 릴리스하려면 보유 수를 0으로 가져와야합니다. 따라서 두 번 .

호프가 도움이됩니다.

+0

+1입니다.요점과 잘 설명되어 :) –

+0

내가 "자기를 사용하는 것을 선호하는 대신 @ 속성 (할당)을 사용하는 것이 가능합니다 ..." – user707342

+0

@ user707342 : 할당을 권장하지 않지만 아래에서 사용할 수 있습니다. self.myVariable = nil; 다시 설정하기 전에 .... – Jhaliya

0

나는 두 번째 부분을 쉽게 설명 할 수 있지만 질문을 완전히 이해할 수 있는지 잘 모르겠다.

- (무효) createLeak {

분명
self.dicParams = [[NSMutableDictionary alloc] init]; 

self.dicParams = [[NSMutableDictionary alloc] init]; 

... 지금

그러나 이것은

- (무효) createAnotherLeak {

self.dicParams = [[NSMutableDictionary alloc] init]; 

self.dicParams = nil; 

self.dicParams = [[NSMutableDictionary alloc] init]; } 

은 할당 된 첫 번째 self.dicParams를 해제하지 않지만이를 nil로 설정 한 다음 새 것으로 재설정하여 모든 참조를 잊어 버립니다. nil로 설정하면 해제와 같지 않습니다. autorelease로 첫 번째 파일을 만든 다음이 파일을 nil로 설정하면 다른 파일이됩니다. 그건 제대로 작동합니다. 그리고 그것은 여러분이 세 번째 예를 통해 여러분이 한 일을 exatcly합니다! 무엇 당신이

self.dicParams의 =의 dicValues을 쓸 때 누수가

당신의 inital 질문에 관해서는 이제

이다;

? 당신은 내가 당신이주의 깊게 애플의 메모리 관리 프로그래밍 가이드를 참조하는 것이 좋습니다 다시

+0

확실히 말할 수는 없지만 악기는 두 개의 NSArrays가있는 다른 객체를 표시하고 self.lines = [NSArray alloc] init]; 파서는 나중에이 배열을 새 값으로 덮어 씁니다. – user707342

0

그것을 놓을 때까지

변수 self.dicParams 그냥 값을 보유해야한다. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

여기에 모두 설명되어 있습니다.

나는 당신이 만들고있는 것을 볼 수있는 몇 가지 분명한 실수가 있습니다.

첫째, init 또는 dealloc에 접근자를 사용하지 않아야합니다. 당신은 유지 속성을 설정할 때 그래서

- (id)init { 
self = [super init]; 

if (self) { 
    self.dicParams = [[NSMutableDictionary alloc] init]; 
    self.dicReferences = [[NSMutableDictionary alloc] init]; 
    self.monitorHandler = [[FtMonitorHandlerService alloc] init]; 
} 
return self; 
} 

가, 둘째

- (id)init { 
self = [super init]; 

if (self) { 
    dicParams = [[NSMutableDictionary alloc] init]; 
    dicReferences = [[NSMutableDictionary alloc] init]; 
    monitorHandler = [[FtMonitorHandlerService alloc] init]; 
} 
return self; 
} 

해야한다는 당신이 해제 할 필요가 당신이 그것을 설정하는 무엇이든.그래서

self.dicParams = [[NSMutableDictionary alloc] init]; 

self.dicParams = [[[NSMutableDictionary alloc] init] autorelease]; 

해야한다 또는 당신이

NSMutableDictionary *newDicParams = [[NSMutableDictionary alloc] init]; 
self.dicParams = newDicParams; 
[newDictParams release]; 
+0

explaination에 감사드립니다. :-)이 관점에서 autorelease로 할당 한 것 이상의 이점을 마지막으로 설명 했습니까? – user707342

+0

자동 해제는 수동으로 해제하는 것이 즉시 적용되기 때문에 자동 해제보다 바람직합니다. autoreleased 오브젝트가 범위를 벗어나면 해제됩니다. – benwong

0

(readwrite, retain, nonatomic) 속성에 대한 @synthesize에 의해 생성 된 세터는 다음과 같은 형태를 수행 할 수 있습니다

- (void) setSomething: (id) newSomething; 
{ 
     if (something != newSomething) { 
      [something release]; 
      something = [newSomething retain]; 
     } 
} 

인스턴스 변수 something이 가리키는 이전 개체는 새 개체가 유지되는 동안 해제됩니다.

실수는 객체 생성입니다. [[NSDictionary alloc] init]으로 사전을 만듭니다. 이 사전은 보유 개수가 1입니다. 설정자가 객체를 보유하므로 새로운 보유 개수는 2입니다. 설정자에게 다시 전화하면 원본 사전의 보유 개수가 올바르게 줄어들고 다시 1이됩니다. 사전을 해제하려면 다시 릴리스해야합니다. 이를 위해 autorelease이 있습니다. autoreleased 오브젝트는 나중에 언젠가 릴리스 될 것입니다. 그래서 속성을 설정하는 올바른 코드는

self.something = [[[NSDictionary alloc] init] autorelease]; 

또는 더 나은 편의를 할당

self.something = [NSDictionary dictionary]; 

당신은 정말 읽고 애플의 메모리 관리 가이드를 이해해야을 사용하는 것 - 그것은 모두 거기에서 설명합니다.

그건 그렇고, 여기에 보유 개수에 대해 이야기했습니다. 그것들에 대해 생각하는 것은 괜찮습니다. 그러나 당신이 생각하는 일이 거의 없으므로 그 가치는 쓸모가 없습니다.

+0

설명해 주셔서 감사합니다. 이것은 나에게 많은 도움이 될 것이다 :-) – user707342

관련 문제