본문 바로가기
프로그래밍 놀이터/iOS

[Effective Objective-C] #36 retainCount 를 사용하지 말라

by 돼지왕 왕돼지 2017. 9. 30.
반응형

 [Effective Objective-C] #36 retainCount 를 사용하지 말라


출처 : Effective Objective-C

arc, arc retaincount, autorelease, compile time constant, no-ops, NSNumber, NSString, release, retain, retainCount, retaincount 0, tagged pointer, true retain count, [Effective Objective-C] #36 retainCount 를 사용하지 말라, 디버깅 용도, 싱글턴 객체, 앱 바이너리, 컴파일 시점 상수, 컴파일 에러, 표시된 포인터


-

NSObject 프로토콜에 정의된 이 메서드로 객체의 현재 리테인 수를 얻을 수 있다.

- (NSUInteger)retainCount



-

그러나 ARC 는 이 메서드를 폐기했다.

실제로 ARC  를 사용하면서 retain, release, autorelease 를 호출하는 것처럼 retainCount 를 호출하면 컴파일러가 에러를 던질 것이다.

이 메서드가 공식적으로 폐기 되었는데도 많은 사람들이 잘못 이해하고 있다.



-

ARC 를 사용하지 않는다면 이 메서드를 사용할 수 있고 컴파일 에러도 받지 않을 것이다.

그렇기 때문에 이 메서드를 사용하지 말아야 하는 이유를 반드시 알아야 한다.



-

리테인 수는 개발자가 기대하는 정보와 완전히 다른 데이터일 수 있다.

이 메서드는 오직 디버깅 용도로만 사용하긴 하지만 보통은 전혀 유용하지 않다.



-

이 메서드가 유용하지 않는 첫 번째 이유는 이 값이 특정 시점의 리테인 수라는 것이다.

이 값은 오토릴리스 풀이 마를 때 일어날 값의 감소를 포함하지 않는다.

이 값은 어쩔 수 없이 실제 리테인 수(true retain count)를 나타내지 않는다.


그래서 다음과 같은 코드는 매우매우 위험하다.

while( [object retainCount] ){

     [object release];

}


객체가 오토릴리스되어 릴리스를 기다리고 있는 상태라면 문제가 생길 수 있다.

그 객체가 오토릴리스 풀에 있었다면 풀이 마를 때 그 객체가 릴리스될 것이다.

하지만 바로 크래시가 발생할 것이다.



-

retainCount 는 절대로 0 을 반환하지 않는다.

객체의 리테인 수가 1일 때 release 가 호출되면 리테인 수를 0 으로 바꾸는 행위를 건너뛰고 바로 할당 해제하는 것이 최적화된 구현일 것이다.

다시 말해 리테인 수를 감소시켜도 리테인 수가 공식적으로 절대 0이 되지 않는 것을 말한다.



-

할당 해제되어야 할 객체가 리테인 수가 양수인 채로 남겨지는 상황이 일어나서는 절대로 안 된다.

이런 상황이 발생하면 이 객체가 왜 릴리스되지 않았고 무엇이 아직 이 객체를 리테인하고 있는지 밝혀야 한다.



-

NSString, NSNumber 등은 보통 싱글턴 객체이다.

NSString 은 가능하다면 싱글턴 객체로 구현된다.

문자열이 컴파일 시점 상수(compile-time constant)일 때, 컴파일러는 특별한 객체를 생성한다.

NSString 객체의 데이터를 앱 바이너리에 둔다.

그리고 실행 시간에 NSString 객체를 생성하는 것 대신 그것을 사용한다.


NSNumber 도 특정 타입의 값을 위한 표시된 포인터(tagged pointer)라는 개념을 사용해서 비슷하게 동작한다.



-

싱글턴의 리테인 수는 절대 바뀌지 않는다.

리테인과 릴리스는 아무런 일을 하지 않는다.(no-ops)

리테인 수가 이와 같이 동작할 수 있다는 사실과 두 개의 싱글턴이 서로 다른 리테인 수를 반환한다는 사실은 이 값(리테인 수)을 사용하지 말아야 하는 것을 다시 한 번 상기시킨다.



-

디버깅 목적으로 리테인 수를 사용하길 원한다면 어떨까?

그렇다 하더라도 보통은 도움이 되지 않는다.

리테인 수는 개발자들이 생각하는 것처럼 정확하지 않다.

객체가 오토릴리스 풀에 있을 수도 있기 때문이다.


또한 다른 라이브러리들이 객체를 리테인/릴리스하는 것으로 인해

리테인 수를 예측할 수 없게 된다.

리테인 수를 확인했을 때 다른 라이브러리가 아닌 여러분의 코드에서 리테인 수를 변경했다고 잘못 가정할 것이다.



-

retainCount 는 언제 사용할 수 있을까?

"절대 사용하지 말라" 가 바로 정답이다.

특히 애플은 공식적으로 ARC 를 사용할 때 이 메서드 사용을 금지하고 있다.




기억할 점


객체의 리테인 수는 유용해 보이지만 보통은 그렇지 않다.

특정 시간의 절대 리테인 수는 객체 생애 주기의 완전한 그림을 보여주지 않기 때문이다.


ARC 를 도입하면서 retainCount 메서드는 폐기되었다.

그리고 이 메서드를 사용하면 컴파일 에러가 일어난다.




반응형

댓글