私は ARC メモリ管理について学んでいて、意味をなさないものに出くわしました。
以下のサンプル コードでは、main() でローカルに割り当てられたオブジェクトは、予想どおり、ポインターが nil に割り当てられると割り当てが解除されます。
しかし、同じタイプのオブジェクトが別の関数で割り当てられ、そのポインタが main() で定義され、そのポインタが nil に設定されている場合、オブジェクトは main 関数が終了するまで割り当て解除されません。それは私には謎です。
以下のコードでは、クラス GRMemoryChecker の 2 つのインスタンスが作成されます。ある場合には main() で直接割り当てられ、別の場合には main() が itemMakerFunc() を呼び出して割り当てを行います。main() を実行すると、ポインタが nil に設定されている場合、関数で割り当てられたインスタンスの割り当てが解除されていないことがログ出力に示されます。つまり、関数の終了時に割り当てが解除されます。
これは、 itemMakerFunc() で作成されたインスタンスには、ポインタが nil に設定される前に 2 人の所有者がいるのに対し、ローカルに作成されたインスタンスには 1 人しかいないことを意味すると思います。
しかし、なぜ?ポインターが nil に設定された時点でまだ存在している他の所有者は? または、他の所有者がまだ存在しない場合、存在しなくなったときにカウンターが減らされなかったのはなぜですか?
GRMemoryChecker.h:
#import <Foundation/Foundation.h>
@interface GRMemoryChecker : NSObject
{
NSString *name;
}
- (id)initWithName:(NSString *)str;
- (void)setName:(NSString *)str;
- (void) dealloc;
@end
GRMemoryChecker.m:
#import "GRMemoryChecker.h"
@implementation GRMemoryChecker
- (id)initWithName:(NSString *)str
{
self = [super init];
if (self)
{
[self setName:str];
}
return self;
}
- (void)setName:(NSString *)str
{
name = str;
}
- (NSString *)description
{
return name;
}
- (void) dealloc;
{
NSLog(@"Destroyed: %@", self);
}
@end
main.m:
#import <Foundation/Foundation.h>
#import "GRMemoryChecker.h"
GRMemoryChecker *itemMakerFunc()
{
return [[GRMemoryChecker alloc] initWithName:@"func-based checker" ];
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
GRMemoryChecker *checkerLocallyCreated = [[GRMemoryChecker alloc] initWithName:@"locally-created checker"];
GRMemoryChecker *checkerFuncBased = itemMakerFunc();
NSLog(@"Before setting func-based checker pointer to nil");
checkerFuncBased = nil;
NSLog(@"After setting func-based checker pointer to nil");
NSLog(@"Before setting locally-created checker pointer to nil");
checkerLocallyCreated = nil;
NSLog(@"After setting locally-created checker pointer to nil");
}
return 0;
}
コンソール出力:
Before setting func-based checker pointer to nil
After setting func-based checker pointer to nil
Before setting locally-created checker pointer to nil
Destroyed: locally-created checker
After setting locally-created checker pointer to nil
Destroyed: func-based checker