alloc retain release dealloc内部実現原理解析
id obj =[ [NSObject alloc]init];
上記NSObjectクラスを呼び出すallocクラスメソッドはNSObjectにある.mのソースコードは以下のように実現される:
+(id) alloc { return [self allocwithzone:NSDefaultMallocZone()]; }
+(id)allocWithZone:(NSZone *)z { return NSALLocateObject (self, 0, z); }
NSAllocateObject関数をallocwithzoneメソッドで呼び出してオブジェクトを割り当てます.次にNSALLocateObject関数を見てみましょう.
`struct obj_layout {
NSUInterger retained;
};
inline id
NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone* zone)
{
int size = ;
id new = NSZoneMalloc(zone, size);
memset(new, 0, size);
new = (id)& ((struct obj_layout *)new)[1];
}
`NSAllocateObject は、NSZoneMAlloc を び すことにより、オブジェクトを するために なメモリ を り てる、その メモリ を0にし、 にシートオブジェクトに るために するポインタである.
NSZone
このクラスはメモリの を するために する である.メモリ り ての に して を う、 の 、 の きさに じてメモリを り て、メモリ の を する.しかし、ARCシステムでは、 にシステムのメモリ が に われており、 メモリを すると、かえってメモリ の の が します.
はNSZoneを したコードです`struct obj_layout {
NSUInterger retained;
};
+(id)alloc
{
int size = sizeof(struct obj_layout) + ;
struct obj_layout *p= (struct obj_layout *)calloc(1, size);
return (id)(p +1);
}
`
allocクラスメソッド obj_layoutのretained は、 カウントを する、オブジェクトメモリヘッダに き まれ、そのオブジェクトメモリブロックはすべて0にして る.
オブジェクトの カウントはretainCountインスタンス で できます
[obj retain] `
-(id)reatin
{
NSIncrementExtreaRefCount (self);
return self;
}
inline void
NSIncrementExtreaRefCount(id anObject)
{
if (((struct obj_layout *)anObject)[-1].retained = UINT_MAX - 1 )
[NSExpression raise: NSInternalInconsistencyException format:@"NSIncrementExtreaRefCount()asked to increment to far");
((struct obj_layout *)anObject)[-1].reatined++;
} `
、releaseインスタンスメソッドの `
-(void)release
{
if (NSDecrementExtraRefCountWasZero(self)) {
[self dealloc];
}
}
NSDecrementExtraRefCountWasZero(id anObject)
{
if (((struct obj_layout *)anObject)[-1].retained == 0)
{
return YES;
}else{
((struct obj_layout *)anObject)[-1].retained--;
return NO;
}
}`
`
-(void)dealloc
{
NSDeallocateObject(self);
}
NSDeallocateObject(id anObject)
{
struct obj_layout * o = &((struct obj_layout *)anObject) [-1];
free(0);
}`
がGNUstepにおけるalloc/retain/release/dellocの である.
りんごの
は のとおりです+alloc+allocWithZone class_createInstance calloc
allocクラスはまずallocWithZone:クラスメソッドを び します.これはGUNstepの と じで、class_を び します.createINstance のソースコードはobjc-runtime-new.mm
retain/release と
-retainedCount __CFDoExternRefOperation CFBasicHashGetCountOfKey
-retain __CFDoExternRefOperation CFBasicHashAddValue
-release __CFDoExternRefOperation CFBasicHashRemoveValue
それぞれのメソッドが び されました_CFDoExternRefOperation は、Core FoundationフレームワークのソースコードでCFRuntime.cの___CFDoExternRefOperation で します. は された ソースコードです.`
int __CFDoExternRefOperation
{
CFBasicHashRef table = (obj);
int count;
switch (op) {
case OPERATION_retainCount;
count = CFBasicHashGetCountOfKey(table, obj);
return count;
case OPERATION_retain;
CFBasicHashAddValue(table, obj);
case OPERATION_release;
CFBasicHashRemoveValue(table, obj);
}
}
`
GNUstepは カウントをオブジェクトがメモリブロックヘッダを する に し、アップルの は カウントテーブルの に する.メモリカードヘッダで カウントを するメリットは、 のコードで カウント メモリブロックとオブジェクト メモリブロックを に できることです.
カウントテーブルにより カウントを する は、オブジェクト メモリブロックの り ては、メモリブロックヘッダ カウントテーブルの レコードにメモリブロックアドレスが されていることを する がなく、 レコードから オブジェクトのメモリブロックに ることができる
***アップルの に する 2 の はデバッグ に な を たしている:***1. により が するメモリブロックが したとしても、 カウントテーブルが することなく、 メモリブロックの を することができる.ツールを してメモリリークを する 、 カウントテーブルの レコードは、 オブジェクトの が するかどうかを するのに ちます.