본문 바로가기
Studynote

[정리] Object-C Chapter 20 메모리 누수 막기

by e.sunie 2018. 11. 3.

Chapter 20

메모리 누수 막기


양방향의 관계 갖기 자식의 포인터를 다시 그 부모를 가리키도록 추가


Asset.h

#import <Foundation/Foundation.h>

@class Employee;


@interface Asset : NSObject

{

NSString *label;

Employee *holder;

unsignedint resaleValue;

}


@property (strongNSString *label;

@property (strong) Employee *holder;

@propertyunsignedint resaleValue;


@end


Asset.m

#import "Asset.h"

#import "Employee.h"


@implementation Asset

@synthesize label, resaleValue, holder;

-(NSString *)description

{

if([self holder]) {

return [NSStringstringWithFormat:@"<%@: $%d , assigned to %@>", [selflabel], [selfresaleValue], [selfholder]];

else {

return [NSStringstringWithFormat:@"<%@: $%d unassigned>", [selflabel], [selfresaleValue]];

}

}

-(void)dealloc

{

NSLog(@"deallocating %@"self);

}

@end



  • 두 관계가 일관된 것인지 확인하는 방법

  • 비품이 직원의 비품 배열에서 나타날 경우는 오직 그 직원이 그 비품의 보유자


  1. 두 관계의 명시적 설정

[vicePresident addAssetsObject:townCar];

[townCar setHolder:vicePresident];


  1. 자식의 포인터를 설정하는 메소드에서 자식을 부모의 컬렉션에 추가

-(void) setHolder : (Employee *)e

{

holder = e;

[e addAssetsObject:self];

}


  1. 자식을 부모의 컬렉션에 추가하는 메소드에서 자식의 포인터를 설정

-(void)addAssetsObject: (Asset *) a {

// assets닐인가?

if (!assets) {

// 배열을만든다.

assets = [[NSMutableArray alloc] init];

}

[assets addObject:a];

[a setHolder:self];

}


  • AddAssetsObject:메서드 확장


→ 그래도 메모리에서 취소가 되지 않음


[유지 사이클]


객체가 메모리에서 취소되어야 메모리 공간이 넒어지는데 그러지 못한 현상

메모리 누수의 원인


solution : Instruments를 이용해 프로파일한다.

  • 프로파일한다

    프로그램이 실행되는 동안 이면에서 무슨일이 일어나는지 면밀히 지켜본다보통 프로파일할 시간을 벌기위해 main()함수 끝에 sleep()을 추가한다.


[약한 참조]


  • 유지사이클을 해결하는 방법

  • 소유권을 주장하지 않는 포인터

  • 상속관계에서 유지사이클을 막는 법?

부모는 자식을 소유해도 자식은 부모를 소유할 수 없도록 설정


#import <Foundation/Foundation.h>

@class Employee;


@interface Asset : NSObject

{

NSString *label;

__weak Employee *holder;

unsignedint resaleValue;

}


@property (strongNSString *label;

@property(weak) Employee *holder;

@propertyunsignedint resaleValue;


@end


  • holder의 약한참조


[약한참조를 0으로 만들기]


  • 약한 참조가 가리키는 객체가 취소되면 그 포인터 변수는 0이 되었다고 말한다.

→ nill로 설정


[조금 더 깊게 참조 수동 카운팅과 ARC]



  1. 참조수동카운팅


  • 유지카운트를 사용하는 방식

  • 객체가 메시지를 명시적으로 받아 유지카운트를 줄이거나 늘릴때만 소유권 변경이 일어난다.

[anObject release];

[anObject retain];


  • 위와 같은 형태는 엑세서 메소드, dealloc 메서드에서 볼 수 있다.

-(void) setHolder:(Employee *)newEmp

{

[newEmp retain];

[holder release];

holder = newEmp;

}

  • 엑세서 메서드 새로운 값이 유지되고 이전 값은 정리

-(void)dealloc

{

[labelrelease];

[holder release];

[superdealloc];

}


  • Dealloc메서드 이전에 유지됐던 모든 객체가 정리


-(NSString *)description

{

NSString *result = [[NSSTringallocinitWithFormat:@"<%@: $%d >",

[selflabel], [selfresaleValue]];

[result autorelease];

return result;


}


  • Description 메서드 문자열을 만들어 리턴

  • release는 자동정리 풀이 비워질 때 받는다.


NSAutoreleasePool *arp = [[NSAutoleasePoolallocinit];

Asset *asset = [[Assetallocinit]];


NSString *d = [assetdescription];


[arp drain];




[유지 카운트 규칙]



  1. alloc, new로 시작, copy가 들어가는 메소드를 사용해서 객체를 만들면 소유권을 갖게 된다.(소유권을 넘겨주는 메소드 – alloc, copy, mutableCopy)

  2. retain 메세지를 통해 객체를 소유하지 않지만 존재 상태를 보장

  3. 객체를 소유하는데 더 이살 필요치 않을 때 release, autorelease메시지 사용

    release : 유지 카운트를 즉시 줄인다.

    autorelease : 자동 정리 풀이 비워질 때

  4. 객체의 소유자가 존재하는 동안 객체는 계속 존재



'Studynote' 카테고리의 다른 글

POJO란?  (0) 2019.04.11

댓글