Objective-C 2.0에서는 Retain count 기반으로 메모리 할당 해제가 관리 됩니다. 
그 규칙은 다음의 3가지 입니다. (Apple의 Memory Management Programming Guide for Cocoa 참조)

 
1. You own any object you create. (니가 만든건 니가 갖는다)
    You "create" an object using a method whose name begin with "alloc" or "new" or contains "copy" (for example, alloc, newObject, or mutableCopy).

2. If you own an object, you are responsible for relinquishing ownership when you have finished with it. (만약 객체를 소유했으면, 다 쓸때 반환하는 것에 대한 책임도 가지게 된다)
    One way to relinquish ownership of an object is to send it a release message, In cocoa terminology, relinquishing ownership of an object is typically referred to as "releasing" an object.

3. If you do now own an object, you must not release it. (직접 만든 객체가 아니면 절대 해제하지 마라)


규칙은 간단합니다. 만든건 책임지고, 안만든건 건드리지 말라. Memory leak을 유발하지 않기 위한 가장 기본적인 원리입니다. 

위의 규칙을 몸소 겪어보고자, 요 한동안 삽질의 연속이었습니다. Retain / Release를 통한 메모리 관리 mechanism을 몸에 베게 하기 위해 일부러 NSAutoreleasePool 객체를 만들지 않고 코딩연습을 했습니다. 그렇게 하면 정확한 프로그래밍을 하지 않으면 leak이 우수수 쏟아질 것으로 생각했기 때문입니다. (그러나 convenience method를 호출할 수 없어 난관이 있었습니다 -_-;)

머 결과는 그닥 보잘것이 없습니다. Web에서 쉽게 찾아볼 수 있는 수준의 결과가 나왔네요. 몇일 동안의 삽질 끝에 알아낸 것을 정리합니다. 

1. NSString에서 initWithXXXX계열의 함수들은 parameter로 받은 객체의 retain count를 1 증가시킨다.
즉 복사가 아닌 reference한다. 사실은 initWithXXXX계열의 함수는 alloc된 객체에 의해서만 가능합니다. 즉, alloc을 호출하기 때문에  retain count가 증가하는 것은 당연한거지요. 이 말은 즉, 직접 release까지 해 주어야 한다는 것입니다.  

2. NSString에서  stringWithXXXX계열의 함수들은 parameter로 받은 객체를 "복사"하고 NSAutoreleasePool에 등록한다.
 즉 객체를 만든 입장에서는 release를 해주지 않아도 된다는 것입니다. 이 함수는 alloc을 호출하지 않고 [NSString stringWithFormat: ~~~] 이런 형식이기 때문에 alloc을 사용자가 명시적으로 호출하지 않습니다. 즉 release하지 않아도 된다는 것입니다. AutoreleasePool을 이용한 release는 delayed release가 됩니다.  이런 stringWithXXXX같이, 사용자가 release를 신경쓰지 않고 autoreleasePool을 이용하도록 하는 함수를 Convenience Method라고 합니다. 

3. Code상에 @"ABCDEF"같이 문자열을 직접 쓰는 것은 객체가 아니기 때문에 해제할 필요도 없다. 문자열을 이용해 initWithString함수를 이용해 만든 NSString객체는 해재할 필요 없다. 

그런데!!! 참 알다가도 모르겠습니다. main함수에서 열심히 retain counter를 올려봤건만... 하나도 release하지 않았는데 프로그램이 종료될 때 까지 leak error가 발생하지 않더군요... 이건 참 모르겠습니다. 물어볼 사람도 없는데 -_-;;
 

#import <Foundation/Foundation.h>

#import "Test.h"


#import <Foundation/Foundation.h>

#import "Test.h"


int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool allocinit];

    Test* test = [[Test allocinit];

    [test printMemberRetainCount];


    NSString* testName = [NSString stringWithFormat@"ABCDEFG"];

    [test setName: testName];

    [test printMemberRetainCount];

    
    [testName
retain];

    NSLog(@"Test Name's retain Count : %d", [testName retainCount]);

    [pool drain];

    

    return 0;

}



저 녹색 글씨부분... 분명히 retain Counter가 1 증가하여 autoreleasePool에서 release시켜도 dealloc안되고 leak이 되어야 하는데... 



어디에도  leak에 대한 error는 없습니다. -_-;; 모르겠네요 -_-


Posted by yunseong