一般に、オブジェクトの割り当てを解除しても、メモリはゼロにされませんが、必要な人は誰でも自由に再利用できます。したがって、割り当て解除されたオブジェクトへのポインタを保持している場合でも、通常はしばらくの間オブジェクトを使用できます(2番目の-release
メッセージの場合と同様)。サンプルコード:
#import <Foundation/Foundation.h>
@interface Foo : NSObject
@property(assign) NSUInteger canary;
@end
@implementation Foo
@synthesize canary;
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
Foo *foo = [[Foo alloc] init];
[foo setCanary:42];
[foo release];
NSLog(@"%li", [foo canary]); // 42, no problem
}
return 0;
}
デフォルトではこれに対するチェックはなく、動作は単に未定義です。環境値を設定するNSZombieEnabled
と、メッセージングコードは割り当て解除されたオブジェクトのチェックを開始し、おそらく予想どおりに例外をスローする必要があります。
*** -[Foo canary]: message sent to deallocated instance 0x100108250
ちなみに、デフォルトのチェックされていないケースは、動作が非常に非決定的である可能性があるため(メモリ使用パターンによって異なります)、メモリエラーのデバッグが非常に難しい理由の1つです。バグはどこかで過剰にリリースされたオブジェクトですが、コードのあちこちで奇妙なエラーが発生する可能性があります。前の例を続ける:
Foo *foo = [[Foo alloc] init];
[foo setCanary:42];
[foo release];
Foo *bar = [[Foo alloc] init];
[bar setCanary:11];
NSLog(@"%li", [foo canary]); // 11, magic! (Not guaranteed.)
とはなぜNSArray
違うのかというとNSMutableArray
、空の配列は確かに特別な獣のように見えます。
NSArray *foo = [[NSArray alloc] init];
NSArray *bar = [[NSArray alloc] init];
NSLog(@"%i", foo == bar); // yes, they point to the same object
だからそれはそれと関係があるかもしれません。ただし、一般的な場合、割り当て解除されたオブジェクトを操作すると、何でも実行される可能性があります。それはうまくいくかもしれないし、うまくいかないかもしれないし、あなたのコーヒーをこぼしたり、核戦争を始めたりするかもしれない。しないでください。