2011-09-02 1 views
1

Je commence à regarder dans IOS Development et j'ai des doutes sur la libération d'objets pour lesquels je n'ai pas stocké de référence .. Je ai donné un coup d'oeil à la question "Libérer un objet sans aiguille?" où il est suggéré d'envoyer le message autorelease à l'objet immédiatement après sa création, et donc j'ai essayé de faire la même chose dans le morceau de code suivant:Erreurs autoéleasing objets juste après leur création

int main(int argc, char *argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSURLResponse * response = nil; 
    NSError * error = nil; 
    NSData * data; 

    data = [NSURLConnection 
      sendSynchronousRequest: [[NSURLRequest requestWithURL: 
             [[NSURL URLWithString: @"http://www.google.it"] 
              autorelease] 
            ] autorelease] 
       returningResponse: &response 
          error: &error]; 

    [data writeToFile: @"/tmp/test.html" 
      atomically:NO]; 

    [data release]; 
    [pool drain]; 

    return 0; 
} 

Je ne pouvais pas essayer d'exécuter le programme dans XCode encore , mais je compile sous linux et le message autorelease envoyé à l'objet NSURLRequest provoque une erreur de segmentation (je pense qu'il n'est pas causé par le message lui-même mais par le drain de la piscine qui essaie de libérer l'objet, grâce au message autorelease) . Quel est le problème avec le message autorelease que j'ai envoyé à l'objet NSURLRequest? Je pense que si le document de référence pour une méthode de classe comme requestWithUrl dit qu'il "crée et retourne une requête d'URL" cela signifie que je suis responsable de libérer l'objet quand j'ai fini de l'utiliser, ai-je tort ? Je voudrais bien comprendre ces règles de gestion de la mémoire avant d'aller plus loin avec autre chose .. J'espère que mes questions ne sont pas trop stupides ;-)

Euh, juste une dernière question: devrais-je publier aussi l'erreur et les données Objets renvoyés par la requête synchrone?

Merci d'avance pour toute aide!

Répondre

3

+requestWithURL: (et d'autres méthodes) retournent déjà des objets auto-libérés, donc vous ne devriez pas leur envoyer une auto-libération supplémentaire.

Des autoreleases supplémentaires dans votre code font que l'objet est sur-publié plus tard et que l'application tombe en panne.

Règle de base pour savoir si vous devez libérer un objet - version requise uniquement si vous créez un objet en utilisant la méthode qui contient 'alloc', 'new', 'copy' dans son nom. Toutes les API standard suivent cette règle et vous devez la suivre lorsque vous développez vos propres méthodes.

Donc code corrigé sera:

int main(int argc, char *argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSURLResponse * response = nil; 
    NSError * error = nil; 
    NSData * data; 

    data = [NSURLConnection 
      sendSynchronousRequest: [NSURLRequest requestWithURL: 
              [NSURL URLWithString: @"http://www.google.it"]                     
       returningResponse: &response 
          error: &error]; 

    [data writeToFile: @"/tmp/test.html" 
      atomically:NO]; 

    [pool drain]; 

    return 0; 
} 

post-scriptum Aucun objet de données et d'erreur ne doit être libéré pour les raisons ci-dessus.

+0

Je tiens à vous remercier tous pour les réponses immédiates! Je me doutais qu'ils étaient autoreleased, maintenant tout est beaucoup plus clair: si j'alloue quelque chose je dois le libérer (ou le marquer pour autorelease plus tard), si je crée une instance en utilisant une méthode de classe comme + requestWithUrl (qui ne contient pas init/copy/new words) Je ne devrais pas le publier sauf si je l'ai retenu pour une raison quelconque. –

+0

@Gianni, exactement! :) – Vladimir

1

Votre code devrait ressembler à ceci:

int main(int argc, char *argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSURLResponse * response = nil; 
    NSError * error = nil; 
    NSData * data; 

    data = [NSURLConnection 
      sendSynchronousRequest: [NSURLRequest requestWithURL:[NSURL URLWithString: @"http://www.google.it"]] returningResponse:&response error: &error]; 

    [data writeToFile: @"/tmp/test.html" 
      atomically:NO]; 

    [pool drain]; 

    return 0; 
} 

Vous n'avez pas besoin d'appeler autorelease à vos objets créés avec les méthodes que \

Vous n'avez pas besoin de libérer data et error..

Toutes les méthodes qui retournent un objet en utilisant la notation suivante NSClass *object = [NSClass classSomeMagicWords]; retourneront l'objet auto-libéré, que vous ne devriez pas libérer si vous n'appelez pas retain.

0

Vous devez supprimer les autoreleases. Dans le développement iOS/Mac OSX, avec les Classes fournies par Apple, la règle est la suivante: si vous créez un objet avec une méthode n'impliquant pas le mot init, vous recevez un objet déjà auto-libéré.

Par exemple:

NSString *blaah = [[NSString alloc] init]; 

reviendriez un objet que vous avez besoin de libérer plus tard. D'autre part, vous obtiendrez un objet autoreleased et si vous le relancez, il se bloquera.

0

Dans la gestion de la mémoire iOS, vous ne possédez que des objets que vous créez en leur allouant de la mémoire ou en les copiant (les méthodes commencent par alloc ou ont "copy" dans leur nom).

Vous avez seulement besoin de les libérer/autorelease si vous les possédez. Des méthodes telles que requestWithURL ou URLWithString renvoient déjà des objets auto-libérés.

Vérifiez this doc sur le site du développeur Apple pour plus d'informations.

Questions connexes