メモリ管理ポリシー


参照カウント環境でのメモリ管理に使用される基本モデルは、NSObject プロトコル で定義されたメソッドと標準的なメソッド命名規則の組み合わせによって提供されます。NSObject クラスは、オブジェクトが割り当て解除されたときに自動的に呼び出される、メソッド dealloc も定義します。この記事では、Cocoa プログラムでメモリを正しく管理するために知っておく必要があるすべての基本的な規則について説明し、正しい使い方の例を示します。


基本的なメモリ管理規則


メモリ管理モデルは、オブジェクトの所有権に基づいています。どのオブジェクトにも 1 人以上の所有者がありえます。オブジェクトに所有者が少なくとも 1 人いる限り、オブジェクトは存在し続けます。オブジェクトに所有者がいない場合、実行時システムは自動的にそれを破棄します。オブジェクトを所有しているときとそうでないときが明確になるように、Cocoa は以下のポリシーを設定します。


簡単な例


ポリシーを説明するために、以下のコード断片を考えてみましょう。


{
    Person *aPerson = [[Person alloc] init];
    // ...
    NSString *name = aPerson.fullName;
    // ...
    [aPerson release];
}


Person オブジェクトは alloc メソッドを使用して作成されるため、不要になったときには release メッセージがその後に送信されます。その person の名前は所有メソッドのいずれかをも使用して回収されないので、release メッセージは送信されません。ただし、この例では autorelease ではなく release を使用しています。


autorelease を使用して遅延解放を送信


遅延 (deffered) release メッセージを送信する必要がある場合 (通常はメソッドからオブジェクトを返すとき) には、autorelease を使用します。たとえば、以下のように fullName メソッドを実装できます。


- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
                                          self.firstName, self.lastName] autorelease];
    return string;
}

あなたは alloc によって返された文字列を所有しています。メモリ管理規則に従うには、参照を失う前に文字列の所有権を放棄しなければなりません。ただし、release を使用すると、文字列は返される前に割り当て解除されます (そして、メソッドは無効なオブジェクトを返します)。autorelease を使用すると、所有権を放棄することを意味しますが、メソッドの呼び出し元は、返された文字列を割り当て解除される前に使用できます。


以下のように fullName メソッドを実装することもできます:


- (NSString *)fullName {
    NSString *string = [NSString stringWithFormat:@"%@ %@",
                                 self.firstName, self.lastName];
    return string;
}


基本的な規則に従って、stringWithFormat: によって返された文字列をあなたは所有していないので、メソッドから文字列を安全に返すことができます。


対照的に、以下の実装は間違っています:


- (NSString *)fullName {
    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@",
                                         self.firstName, self.lastName];
    return string;
}


命名規則によると、fullName メソッドの呼び出し元は返された文字列を所有していることを示すものは何もありません。したがって、呼び出し元は返された文字列を解放する理由がなく、したがってリークします。


参照で返されたオブジェクトは所有していない


Cocoa のいくつかのメソッドは、オブジェクトが参照によって返されることを指定します (つまり、ClassName ** または id * 型の引数をとります)。一般的なパターンは、initWithContentsOfURL:options:error: (NSData) および initWithContentsOfFile:encoding:error: (NSString) のように、エラーが発生した場合にエラーに関する情報を含む NSError オブジェクトを使用することです。


これらの場合、既に説明したのと同じ規則が適用されます。これらのメソッドのいずれかを呼び出すと、 NSError オブジェクトを作成しないので、そのオブジェクトを所有しません。したがって、この例に示すように、解放する必要はありません。


NSString *fileName = <#Get a file name#>
NSError *error;
NSString *string = [[NSString alloc] initWithContentsOfFile:fileName
                        encoding:NSUTF8StringEncoding error:&error];
if (string == nil) {
    // Deal with error...
}
// ...
[string release];


オブジェクトの所有権を放棄するため dealloc の実装

NSObject クラスは、オブジェクトに所有者がなく、そのメモリが再利用されたときに自動的に呼び出される dealloc メソッドを定義します。Cocoa の用語では、これは "解放(freed)" または "割り当て解除(deallocated)" です。dealloc メソッドの役割は、オブジェクトの独自のメモリを解放し、オブジェクトインスタンス変数の所有権を含め、保持するすべてのリソースを廃棄することです。


以下の例は、Person クラスに対して dealloc メソッドを実装する方法を示しています。


@interface Person : NSObject
@property (retain) NSString *firstName;
@property (retain) NSString *lastName;
@property (assign, readonly) NSString *fullName;
@end
 
@implementation Person
// ...
- (void)dealloc
    [_firstName release];
    [_lastName release];
    [super dealloc];
}
@end


重要: 別のオブジェクトの dealloc メソッドを決して直接呼び出さないで下さい。
実装の 最後 にスーパークラスの実装を呼び出さなければなりません。
システム・リソースの管理をオブジェクトの寿命に結びつけるべきではありません。dealloc を使って希少リソースを管理しない を参照してください。
アプリケーションが終了しても、オブジェクトは deallocz メッセージを送信しないことがあります。プロセスのメモリは終了時に自動的に消去されるため、すべてのメモリ管理メソッドを呼び出すよりもオペレーティングシステムがリソースをクリーンアップできるようにする方が効率的です。


Core Foundation は、類似するが違う規則を使用


Core Foundation オブジェクトにも同様のメモリ管理規則があります (Core Foundation のためのメモリ管理プログラミングガイド を参照の事)。 しかし、Cocoa と Core Foundation の命名規則は異なります。特に、Core Foundation の 作成規則(作成規則 参照) は、Objective-C オブジェクトを返すメソッドには適用されません。たとえば、以下のコードの断片では、myInstance の所有権を放棄する責任はあなたには ありません


MyClass *myInstance = [MyClass createInstance];


前の章 次の章



目次
Xcode 10 の新機能

  • メモリ管理について
  • 一目見て
    メモリー関連の問題を防ぐ良い方法
    分析ツールを使用してメモリの問題をデバッグ
  • メモリ管理ポリシー
  • 基本的なメモリ管理規則
  • オブジェクトの所有権を放棄するため dealloc の実装
    Core Foundation は、類似するが違う規則を使用
  • 実践的なメモリ管理
  • アクセッサメソッドを使用してメモリ管理を容易に
  • 弱い参照を使用して循環保持を避ける
    使用中のオブジェクトの割り当て解除を避ける
    dealloc を使って希少リソースを管理しない
    コレクションに含まれるオブジェクトを所有
    保持カウントを使用して所有権ポリシーの実装
  • 自動解放プールブロックの使用
  • 自動開放プールブロックについて
    ローカルの自動開放プールブロックを使用しピークメモリ使用量を削減
    自動解放プールブロックとスレッド
  • 文書改訂履歴












  • トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)












    トップへ(Core Foundation)