2011-08-11 8 views
0

Obj-C의 초보자이며 몇 가지 사항을 실험하고 있습니다. 누설 문제가 발생하여 그 뒤에 논리적 인 이유를 알고 싶습니다.목표 - C - NSMutableAttributedString 누설

다음 코드 조각 누출 :

(textViewAttrStr is an instance variable of type NSMutableAttributedString) 

-(void) init:(NSString*)str 
{ 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str]; 
[textViewAttrStr appendAttributedString:part1String]; 
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"]; 
[textViewAttrStr appendAttributedString:part2String]; 
[textViewAttrStr retain]; 

[part1String release]; 
[part2String release]; 

[pool drain]; 
} 

-(void) dealloc 
{ 
if(textViewAttrStr != nil) 
{ 
    [textViewAttrStr release]; 
} 

[super dealloc]; 
} 

다음 코드 을 누설하지 않는 동안 :

-(void) init:(NSString*)str 
{ 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 
NSMutableAttributedString *part1String = [[NSMutableAttributedString alloc] initWithString:str]; 
[tvas appendAttributedString:part1String]; 
NSMutableAttributedString *part2String = [[NSMutableAttributedString alloc] initWithString:@"!!!"]; 
[tvas appendAttributedString:part2String]; 

textViewAttrStr = tvas; 
[textViewAttrStr retain]; 

[part1String release]; 
[part2String release]; 
[tvas release]; 

[pool drain]; 
} 

-(void) dealloc 
{ 
if(textViewAttrStr != nil) 
{ 
    [textViewAttrStr release]; 
} 

[super dealloc]; 
} 

누군가가 이유를 설명 할 수 있습니까?

+0

빠른 답변을 보내 주셔서 감사합니다. 이것은 메모리 관리를 좀 더 쉽게 해줍니다. :) –

답변

0

두 번째 예는 첫 번째 예에서 누수가 왜 실험을 선택이 끝난 그래서 당신이 이해하지 못하는 것을 보여줍니다 textViewAttrStr로 만들 때 이미 유지되기 때문에 것을 제거해야 주위에, 이해할 수있는 접근처럼 보인다.

두 번째 예에서 textViewAttrStr 및 tav는 본질적으로 동일합니다. 그것들은 메모리의 같은 객체에 대한 참조 (또는 포인터)입니다.

그래서, 당신이 할 때

textViewAttrStr = tvas; 
[textViewAttrStr retain]; 
//... 
[tvas release]; 

이 객체에 유지하기 위해 호출이 개체에 출시 할 수있는 호출로 상쇄된다. 이것은 거의 아무것도하지 않고있다. 여기서 retain 및 release 호출을 제거하면 동일한 기능을 제공합니다. 일단 이것을 제거하면 객체는 alloc을 호출했기 때문에 참조 카운트가 1이고, dealloc이 도달하면 0에 도달하여 해제됩니다.

이제 첫 번째 예제에서 객체가 alloc'ed (참조 횟수 1)되고 유지 된 (참조 횟수 2), dealloc 조회수가되면 참조 횟수 1에 도달하고 객체는 풀려 나서 누출되지 않아야한다. 따라서 여기에있는 해결책은 유지할 통화를 제거하는 것입니다.

그런데 nil에 메시지를 보내면 아무 작업도 수행하지 않기 때문에 개체가 해제 메시지를 보내기 전에 nil이 아닌지 확인해야합니다.

1

첫 번째 예 :

textViewAttrStr = [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 
//... 
[textViewAttrStr retain]; 

두 번째 예

NSMutableAttributedString* tvas = [[NSMutableAttributedString alloc] initWithString:@"Hello "]; 
//... 
[tvas release]; 

이제 첫 번째 예를 들어, 당신은 ALLOC/init'd했고 으악, 그것을 유지 것을 볼 수 있습니다.

두 번째 예에서는 제대로/init'd를 할당 한 다음 릴리스했습니다.

간단한 규칙 :/init 또는 copy 또는 retain을 할당하면 어느 시점에서 해제해야합니다. 클래스 변수 인 경우 dealloc에서 해제하고, 그렇지 않으면 범위를 벗어나기 전에 해제하십시오.

2

첫 번째 예제의 문제점은 여분의 유지입니다. 당신은 당신이 [[NSMutableAttributedString alloc] initWithString:@"Hello "];

//Remove this line in the first example 
[textViewAttrStr retain];