Objective Cメモリ管理:autorelease
2540 ワード
本当にautoreleaseを理解できれば、Objective cのメモリ管理を理解することができます.Autoreleaseは実際にはreleaseの呼び出しを遅らせただけで、各Autoreleaseについては、システムは現在のAutorelease poolにObjectを入れただけで、poolが解放されると、poolのすべてのObjectがReleaseを呼び出す.
〔1〕Iphoneプロジェクトでは、デフォルトのAutorelease poolが表示されます.プログラムが開始されたときに作成され、プログラムが終了したときに破棄されます.Autoreleaseの理解によると、すべてのautorelease poolのオブジェクトがプログラムが終了したときにreleaseされるのではないでしょうか.これはメモリ漏洩と何の違いがありますか.
答えは、RunloopごとにAutorelease poolが暗黙的に作成され、すべてのrelease poolがCallStackのようなスタック構造を構成し、各Runloopが終了すると、現在のスタックトップのAutorelease poolが破棄され、このpoolの各Objectがreleaseされます.
ではRunloopとは何ですか?UIイベント、Timer call、delegate callは、新しいRunloopになります.例は次のとおりです.
[2]なぜAutoreleaseが必要なのか.
2.1)多くのC/C++が回ってきたプログラマーは、このauto releaseは何がいいのか、C/C++のように、自分で申請して、自分で釈放して、完全にコントロールできませんか、このauto relaseは完全にコントロールできません.いつ本当のreleaseになるか分かりません.私の理解には、各関数が自分の申請の対象に責任を負い、自分で申請し、自分で解放することができ、この関数の呼び出し者は内部申請の対象の管理に関心を持つ必要はありません.以下の例では,Func 1の呼び出し者はobjの解放に関心を持つ必要はない.
実際に[NSString stringWithFormat:]のようなコンストラクション関数で返されるオブジェクトはautoreleaseです.
2.2)autorelease poolは、頻繁にメモリを申請/解放することを避けるために使用されます(poolの役割です).これは比較的理解しやすいはずです.
まとめ:1)Autorelease poolの生存周期に注意し,Runloopを理解し,オブジェクトが解放された後に使用しないようにする.
2)[NSString stringWithFormat:]このような関数が返すオブジェクトは自分でreleaseする必要はありません.autoreleaseされています.グローバルオブジェクトとして使用したい場合は、自分でretainし、解放してからreleaseしなければなりません.
〔1〕Iphoneプロジェクトでは、デフォルトのAutorelease poolが表示されます.プログラムが開始されたときに作成され、プログラムが終了したときに破棄されます.Autoreleaseの理解によると、すべてのautorelease poolのオブジェクトがプログラムが終了したときにreleaseされるのではないでしょうか.これはメモリ漏洩と何の違いがありますか.
答えは、RunloopごとにAutorelease poolが暗黙的に作成され、すべてのrelease poolがCallStackのようなスタック構造を構成し、各Runloopが終了すると、現在のスタックトップのAutorelease poolが破棄され、このpoolの各Objectがreleaseされます.
ではRunloopとは何ですか?UIイベント、Timer call、delegate callは、新しいRunloopになります.例は次のとおりです.
NSString* globalObject;
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
globalObject = [[NSString alloc] initWithFormat:@"Test"];
NSLog(@"Retain count after create: %d", [globalObject retainCount]); // output 1.
[globalObject retain];
NSLog(@"Retain count after retain: %d", [globalObject retainCount]); // output 2.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(@"Retain count after Button click runloop finished: %d", [globalObject retainCount]);
// 1. Button click loop finished, it's autorelease pool released, globalObject get released once.
}
-(IBAction)onButtonClicked
{
[globalObject autorelease];
NSLog(@"Retain count after autorelease: %d", [globalObject retainCount]);
// 2。 Autorelease call, globalObject AutoreleaePool。
}
[2]なぜAutoreleaseが必要なのか.
2.1)多くのC/C++が回ってきたプログラマーは、このauto releaseは何がいいのか、C/C++のように、自分で申請して、自分で釈放して、完全にコントロールできませんか、このauto relaseは完全にコントロールできません.いつ本当のreleaseになるか分かりません.私の理解には、各関数が自分の申請の対象に責任を負い、自分で申請し、自分で解放することができ、この関数の呼び出し者は内部申請の対象の管理に関心を持つ必要はありません.以下の例では,Func 1の呼び出し者はobjの解放に関心を持つ必要はない.
ClassA *Func1()
{
ClassA *obj = [[[ClassA alloc]init]autorelease];
return obj;
}
実際に[NSString stringWithFormat:]のようなコンストラクション関数で返されるオブジェクトはautoreleaseです.
2.2)autorelease poolは、頻繁にメモリを申請/解放することを避けるために使用されます(poolの役割です).これは比較的理解しやすいはずです.
まとめ:1)Autorelease poolの生存周期に注意し,Runloopを理解し,オブジェクトが解放された後に使用しないようにする.
2)[NSString stringWithFormat:]このような関数が返すオブジェクトは自分でreleaseする必要はありません.autoreleaseされています.グローバルオブジェクトとして使用したい場合は、自分でretainし、解放してからreleaseしなければなりません.