Appel à dealloc initialisation?
-
27-09-2019 - |
Question
Je suis en train d'écrire un cadre et j'ai un objet avec une méthode d'initialisation personnalisée:
@implementation OSDatabase
@synthesize database;
// MEM
- (void)dealloc {
sqlite3_close(database);
[super dealloc];
}
// INIT
- (id)initWithDatabasePath:(NSString *)path error:(NSError **)error {
if (self = [super init]) {
if (!sqlite3_open_v2([path UTF8String], &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
error = [NSError errorWithDomain:@"OSDatabaseErrorDomain" code:1 userInfo:nil];
[self dealloc];
return nil;
}
}
return self;
}
@end
Est-il sûr d'appeler dealloc
à l'intérieur d'une méthode de init
si une erreur occoured? Je ne suis pas sûr à ce sujet et la gestion de la mémoire est l'une des choses les plus importantes dans ma vie.
Merci.
La solution
NonEst-il sûr d'appeler dealloc à l'intérieur d'une méthode d'initialisation si une erreur occoured?
. Envoyer -release
comme vous le feriez partout ailleurs. Même dans -init
vous ne pouvez pas garantir que le nombre actuel est conserviez 1.
Pourquoi vous devez envoyer jamais -dealloc
sauf dans [super dealloc]
-dealloc
? La raison est que vous ne pouvez pas garantir que jamais quelque chose d'autre a aussi une référence à votre objet, même dans le -init
de votre objet, car le [super init]
peut choisir de conserver l'objet.
Si l'objet retourné par [super init]
a retain compte de 1, l'envoi -release
aura le même effet que l'envoi -dealloc
. Si elle a un retain compte de plus de 1, quelque chose d'autre pense qu'il est propriétaire de l'objet et deallocing il partirait avec un pointeur invalide, -release
est toujours la bonne chose à faire.
En outre, ceci:
while([self retainCount] != 0){[self release];}
entraînerait une boucle infinie et est une idée terrible pour un certain nombre de raisons. Retain compte d'objets ne vont jamais à 0. -release
ressemble à quelque chose comme ceci:
- (id)release
{
if (retainCount == 1)
{
[self dealloc];
}
else
{
retainCount--;
}
}
de sorte que la boucle décrémenter le conserver à compter 1, puis appeler sans cesse dealloc toujours ou jusqu'à ce que la corruption du tas, il a causé conduit à un défaut de seg.
En plus de ne jamais atteindre zéro, Retain peut être UINT_MAX
(par exemple dans littéraux chaîne ou numérique) qui signifie familièrement « cet objet ne doit jamais être désalloué ». Si le nombre est de conserver UINT_MAX
, -release
ne décrémenter.
Autres conseils
Par docs vous ne devriez jamais appeler directement dealloc - méthode seulement [super dealloc]
dans votre dealloc personnalisé.
Je pense appeler release
devrait faire au lieu que prévu (au moins si vous utilisez la méthode d'initialisation uniquement en configuration standard alloc-init).
Comme Vladimir dit que vous ne devriez jamais appeler directement dealloc
. lorsque le nombre de conserver un objet atteint 0, Cocoa appelle automatiquement dealloc
.