0

Est-ce que quelqu'un pourrait m'aider à repérer la fuite? Je ne sais pas vraiment où ma fuite est. Donc, je vais poster mon code ici et j'espère que quelqu'un peut le repérer pour moi. Dans l'instrument de fuite, il est dit que le cadre responsable est dispatch_semaphore_create que je n'appelle pas?Objective-C - Les fuites de profilage montrent que la fuite de Grand Central Dispatch

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 

     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 

     dispatch_group_t group = dispatch_group_create(); 

     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

      if ([defaults boolForKey:@"notFirstRunSeminars"]) { 

       BOOL isUpdated = self.seminarsParser.seminarsAreUpdated; 

       if (isUpdated) { 
        DLog(@"Seminars have been updated"); 

        [[NSNotificationCenter defaultCenter] 
        postNotificationName:@"updateSeminarsTable" 
        object:nil]; 

        [[[[[self tabBarController] tabBar] items] objectAtIndex:kSeminarsTabIndex] setBadgeValue:self.seminarsParser.numberOfNewSeminars]; 
        self.seminarsParser.numberOfNewSeminars = nil; 

       } 
      } 
     }); 

     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

      if ([defaults boolForKey:@"notFirstRunCareers"]) { 

       BOOL isUpdated = self.careersParser.careersAreUpdated; 

       if (isUpdated) { 
        DLog(@"Careers have been updated"); 

        [[NSNotificationCenter defaultCenter] 
        postNotificationName:@"updateCareersTable" 
        object:nil]; 

        [[[[[self tabBarController] tabBar] items] objectAtIndex:kCareersTabIndex] setBadgeValue:self.careersParser.numberOfNewCareers]; 
        self.careersParser.numberOfNewCareers = nil; 

       } 
      } 
     }); 

     dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

      if ([defaults boolForKey:@"notFirstRunOffices"]) { 

       BOOL isUpdated = [officesParser officesAreUpdated]; 

       if (isUpdated) { 
        DLog(@"Offices have been updated"); 

        [[NSNotificationCenter defaultCenter] 
        postNotificationName:@"updateOfficesTable" 
        object:nil]; 
       } 
      } 
     }); 

     dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

      [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 

     }); 

    }); 

Répondre

0

Où libérez-vous le groupe une fois que vous avez terminé, puisque vous créez un groupe dans le bloc asynchrone le plus externe? C'est le seul objet que je peux vous voir créer et qui n'est pas publié correctement. Incidemment, un groupe crée un sémaphore dans les coulisses (tout un groupe de dispatching en fait, c'est du sucre syntaxique autour d'un sémaphore de dispatch interne), c'est pourquoi les instruments le signalent de cette façon.

3

Le problème zeroeth: Que fuit? Comme je n'ai pas vu de fuite évidente en analysant votre programme, voici le problème le plus probable: Les objets UIKit ne sont pas threadsafe et ne doivent être mis à jour qu'à partir du thread principal, sauf s'ils entrent dans un autre thread.

Notez également que NSNotification sont affichés sur le thread appelant. Cela signifie que tous vos accès et mises à jour de type UIKit doivent être effectués sur le thread principal. Et oui, cela peut introduire des fuites ou des erreurs de thread pour lesquelles vous devriez considérer comme un comportement indéfini.

+0

Donc, puisque mes notifications sont essentiellement un appel à 'UITableView' à 'reloadData' je devrais mettre les appels "post notification" dans les threads principaux? –

+1

@Peter Correct. Si vous voulez voir comment votre programme circule dans le débogueur, ajoutez 'assert ([NSThread isMainThread])' 'à toutes les méthodes qui appellent directement ou indirectement les objets UIKit (messages directs, lectures/écritures de propriété, notifications, rechargements de tables, etc.). En pratique, vous pouvez * envoyer * un message aux objets UIKit pour accéder à * votre * implémentation/propriétés si vous vous assurez que vos implémentations sont sûres pour les threads * et * si elles n'entrent pas dans l'implémentation des objets UIKit. Une autre idée fausse commune est que 'atomic_property == thread safe', mais ce n'est pas threadsafe. – justin

+0

Malheureusement, je reçois les mêmes fuites de mémoire (Malloc 64 octets) après avoir placé l'appel dans un thread principal. Le code que vous voyez ci-dessus est mis à l'intérieur de '- applicationWillEnterForeground:' de sorte que chaque fois que je reprends l'application, j'ai la fuite de mémoire. Mais quand j'y pense. Ce n'est pas cette notification de publication qui cause la fuite de mémoire parce que j'obtiens les fuites même si 'isUpdated' est' NON'. Ce qui donne? –

Questions connexes