Comportamento inaspettato della classe Singleton su iPhone, sto facendo qualcosa di sbagliato?

StackOverflow https://stackoverflow.com/questions/1002364

  •  05-07-2019
  •  | 
  •  

Domanda

Sto implementando una classe singleton come segue:

static Singleton* _singletonInstance;

@implementation Singleton

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

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

l'inizializzazione viene chiamata solo la prima volta che qualcuno chiama istanza. Ho quindi un metodo che posso chiamare per impostare alcune variabili di istanza. Quindi finisce per apparire così.

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

Quando ottengo un'istanza di questo singleton all'interno di un oggetto, funziona bene la prima volta; Tuttavia, dopo che ho deallocato e creato una nuova copia dell'oggetto che necessita di un'istanza del singleton, ricevo un errore BAD ACCESS quando provo a chiamare la funzione di installazione.

Solo per testare le cose stampo l'indirizzo dell'istanza prima di effettuare la chiamata di configurazione ed entrambe le volte riportano lo stesso indirizzo, ma quando controllo il registro errori per la chiamata BAD ACCESS, elenca un indirizzo di memoria completamente diverso.

Qualcuno ha qualche idea del perché questo puntatore all'istanza sembra avere un bell'aspetto quando lo stampo, ma quando faccio una chiamata, sembra che indichi dati casuali?

È stato utile?

Soluzione

Il valore del puntatore sembra valido perché in precedenza lo era, ma molto probabilmente la memoria è stata liberata, motivo per cui ciò a cui sembrano dati casuali.

Hai acquisito un riferimento con il tuo [[Singleton alloc] init] sopra, ma c'è un rilascio da qualche altra parte che potrebbe essere in esecuzione? Scommetto che il tuo codice sta chiamando istanza , e quindi rilasci più tardi, anche se il tuo codice non ha mai acquisito un riferimento. E questo non dovrebbe essere necessario per un singleton comunque. Solo un'ipotesi ...

Altri suggerimenti

Stai distribuendo il tuo _singletonInstance da qualche parte?

Sto usando una versione molto più complessa, ma molto stabile del modello Singleton (presa con la descrizione da 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;
}

Il codice di Valerii è migliore per l'implementazione di un singleton, ma il problema è quasi certamente che il codice che chiama [istanza Singleton] funziona come se avesse la proprietà senza effettivamente assumerne la proprietà usando il mantenimento, e successivamente lo rilascerà.

Cerca il tuo bug e leggi la Gestione della memoria regole .

Inoltre, in Xcode, abilita NSZombieEnabled e la console ti mostrerà quando prova a inviare un messaggio all'oggetto dopo che è stato rilasciato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top