alloc retain release dealloc内部実現原理解析

4247 ワード

Foundationフレームワークは公開されていないため、まずGNUstepを用いて説明する
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. により が するメモリブロックが したとしても、 カウントテーブルが することなく、 メモリブロックの を することができる.ツールを してメモリリークを する 、 カウントテーブルの レコードは、 オブジェクトの が するかどうかを するのに ちます.