2009-06-16 19 views
1

次のように私はシングルトンクラスを実装しています:iPhoneで予期しないシングルトンクラスの動作が発生しました。何か間違っていますか?

static Singleton* _singletonInstance; 

@implementation Singleton 

+(void)initialize 
{ 
    _singletonInstance = [[Singleton alloc] init]; 
} 

+(Singleton*)instance 
{ 
    return(_singletonInstance); 
} 

だけで、誰かがインスタンスを呼び出し初めて呼び出される初期化します。私はいくつかのインスタンス変数を設定するために呼び出すことができるメソッドを持っています。だからこのように見える。私は、オブジェクト内でこのシングルトンのインスタンスを取得する場合

_singleton = [Singleton instance]; 
[_singleton setupWithParams: blah]; 

は、それが初めて正常に動作します。しかし、私がdeallocし、シングルトンのインスタンスを必要とするオブジェクトの新しいコピーを作成した後、私はセットアップ機能を呼び出そうとするとBAD ACCESSエラーが出ます。

セットアップコールを行う前に、私はインスタンスのアドレスを出力し、両方の時間に同じアドレスを報告しますが、BAD ACCESS呼び出しのエラーログをチェックすると、完全に異なるメモリアドレスがリストされます。

私はそれを印刷すると、このポインタがうまく見えるように見える理由は誰にもありますが、それを呼び出すと、一見ランダムなデータを指していますか?

+0

ありがとう、それはまさにそれでした。クラスはもともと普通のクラスで、私は昨夜それをSingletonに変えました。私がinstatiation呼び出しを置き換えている間、私は完全にリリース呼び出しを削除するのを忘れてしまった。 – Skyler

答えて

3

ポインタの値は以前と同じように見えますが、メモリがフリーである可能性が高いため、ポインターの値はランダムなデータのように見えます。

上記の[[Singleton alloc] init]で1つのリファレンスを取得しましたが、実行中の可能性があるreleaseがありますか?私はあなたのコードがinstanceを呼び出し、その後release-後で、あなたのコードが決して参照を取得しなかったとしても、賭けていると思います。とにかくシングルトンには必要ないはずです。ただの推測...

1

_singletonInstanceを別の場所に割り当てていませんか?

1

私ははるかに複雑使っていますが、(Brandon "Quazie" Kwaselow Blogからの説明で撮影)シングルトンテンプレートの非常に安定したバージョン:

static SampleSingleton *sharedSampleSingletonDelegate = nil; 

+ (SampleSingleton *)sharedInstance { 
    @synchronized(self) { 
     if (sharedSampleSingletonDelegate == nil) { 
     [[self alloc] init]; // assignment not done here 
     } 
    } 
    return sharedSampleSingletonDelegate; 
} 

+ (id)allocWithZone:(NSZone *)zone { 
    @synchronized(self) { 
     if (sharedSampleSingletonDelegate == nil) { 
     sharedSampleSingletonDelegate = [super allocWithZone:zone]; 
     // assignment and return on first allocation 
     return sharedSampleSingletonDelegate; 
     } 
    } 
    // on subsequent allocation attempts return nil 
    return nil; 
} 

- (id)copyWithZone:(NSZone *)zone 
{ 
    return self; 
} 

- (id)retain { 
    return self; 
} 

- (unsigned)retainCount { 
    return UINT_MAX; // denotes an object that cannot be released 
} 

- (void)release { 
    //do nothing 
} 

- (id)autorelease { 
    return self; 
} 
+0

ありがとうValerii、それは実装を調べるのに良いことのように見えます。 – Skyler

1

・バレリーのコードは、シングルトンを実装するためのより良いですが、問題はほぼ確実に[Singleton instance]を呼び出すコードが所有権を持っているかのように動作していて、retainを使用して所有権を実際に取っておき、後で解放するということです。

あなたのバグを見つけて、Memory Managment Rulesを読んでください。

また、Xcodeのenable NSZombieEnabledで、リリース後にオブジェクトにメッセージを送信しようとするとコンソールに表示されます。

+0

Peterさん、ありがとうございました。次回は、私はうんざりしたポインタ呼び出しを実行してNSZombieEnabledを使用します。 – Skyler

関連する問題