2

の驚くべき動作に気づいたNSArrayので、この質問を投稿しています。

次のようなメソッドを追加しました。

- (IBAction) crashOrNot
{
   NSArray *array = [[NSArray alloc] init];
   array = [[NSArray alloc] init];
   [array release];
   [array release];
}

理論的には、このコードはクラッシュします。しかし、私の場合、それは決してクラッシュしませんでした!

を変更しNSArrayましNSMutableArrayたが、今回はアプリがクラッシュしました。なぜこれが起こるのか、なぜNSArrayクラッシュしてNSMutableArrayクラッシュしないのですか?

4

2 に答える 2

7

一般に、オブジェクトの割り当てを解除しても、メモリはゼロにされませんが、必要な人は誰でも自由に再利用できます。したがって、割り当て解除されたオブジェクトへのポインタを保持している場合でも、通常はしばらくの間オブジェクトを使用できます(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

だからそれはそれと関係があるかもしれません。ただし、一般的な場合、割り当て解除されたオブジェクトを操作すると、何でも実行される可能性があります。それはうまくいくかもしれないし、うまくいかないかもしれないし、あなたのコーヒーをこぼしたり、核戦争を始めたりするかもしれない。しないでください。

于 2012-11-05T14:15:09.760 に答える
3

私が考えることができる最も簡単なことは、空NSArrayはFoundationフレームワークのある種の「定数」であるということです。たとえば、NSStringリテラルに似たオブジェクトで、retainCount(呼び出す場合は)-1になります。決して-dealloc'd。

于 2012-11-05T14:14:44.970 に答える