EXC mauvaise INSTRUCTION (code=EXC I386 INVOP, subcode=0x0) sur le sémaphore d'expédition disposer

je reçois EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) sur dispatch_semaphore_dispose mais je ne sais pas vraiment comment trouver la cause profonde de cela. Mon code utilise dispatch_async, dispatch_group_enter et ainsi de suite.

mise à jour: La cause du crash est due au fait que webserviceCall (voir code ci-dessous) n'appelle jamais oncompletionet que lorsque le code est lancé à nouveau, J'ai eu L'instruction error EXC_BAD_INSTRUCTION. J'ai vérifié c'est effectivement le cas, mais vous ne savez pas pourquoi ou comment l'empêcher.

enter image description here

Code:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t group = dispatch_group_create();

     for (...) {
        if (...) {
            dispatch_group_enter(group);
            dispatch_async(queue, ^{

               [self webserviceCall:url onCompletion:^{
                     dispatch_group_leave(group);
               }];
            });
        }
    }

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
    dispatch_sync(queue, ^{
        // call completion handler passed in by caller
    });
});
33
demandé sur Boon 2014-06-21 06:40:51

8 réponses

à Partir de votre trace de la pile EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) est survenue parce que dispatch_group_t a été libéré alors qu'il était encore verrouillé (en attente de dispatch_group_leave).

Selon ce que vous avez trouvé, c'est ce qui s'est passé :

  • dispatch_group_t group a été créé. groupconserver count = 1.
  • -[self webservice:onCompletion:] capturé l' group. groupconserver count = 2.
  • dispatch_async(...., ^{ dispatch_group_wait(group, ...) ... }); capturé l' group nouveau. group's compte de retenue = 3.
  • quitter la portée actuelle. group a été libéré. groupconserver count = 2.
  • dispatch_group_leave n'a jamais été appelé.
  • dispatch_group_wait était temps mort. dispatch_async bloc terminé. group a été libéré. groupconserver count = 1.
  • vous avez rappelé cette méthode. Lorsque -[self webservice:onCompletion:] a été appelé de nouveau, l'ancien onCompletion bloc a été remplacé par le nouveau. Donc, la vieille group a publier. groupconserver count = 0.group a été libéré. Qui ont abouti à l' EXC_BAD_INSTRUCTION.

Pour résoudre ce problème, je suggère que vous devriez chercher à savoir pourquoi -[self webservice:onCompletion:] ne pas appeler onCompletion bloquez et réparez. Ensuite, assurez-vous que le prochain appel à la méthode se produira après l'appel précédent a terminé.


dans le cas où vous permettez à la méthode d'être appelée plusieurs fois si les appels précédents ont fini ou non, vous pourriez trouver quelqu'un de tenir group pour vous :

  • vous pouvez changer le délai de 2 secondes à DISPATCH_TIME_FOREVER ou un délai raisonnable que tous -[self webservice:onCompletion] doivent appeler onCompletion blocs par le temps. De sorte que le bloc dispatch_async(...) va la garder pour vous.

    Ou
  • Vous pouvez ajouter group dans une collection, comme NSMutableArray.

je pense que c'est la meilleure approche pour créer une classe dédiée à cette action. Lorsque vous voulez faire des appels à webservice, vous créez alors un objet de la classe, appelez la méthode dessus avec le bloc d'achèvement qui lui passera qui libérera l'objet. Dans la classe, il y a un ivar dispatch_group_t ou dispatch_semaphore_t.

37
répondu 3329 2014-06-23 18:42:46

Mon problème a été pris IBOutlet mais ne s'est pas connecté avec interface builder et utiliser dans le fichier swift.

8
répondu Mrugesh Tank 2016-01-22 12:10:23

j'ai eu une autre question qui m'a amenée à cette question, qui sera probablement plus fréquente que la question de la réponse exagérée dans la réponse acceptée.

la cause fondamentale est que notre bloc d'achèvement a été appelé deux fois en raison du mauvais si/d'autre fallthrough dans le réseau du gestionnaire, conduisant à deux appels d' dispatch_group_leave pour chaque appel à dispatch_group_enter.

bloc D'achèvement appelé plusieurs fois:

dispatch_group_enter(group);
[self badMethodThatCallsMULTIPLECompletions:^(NSString *completion) {

    // this block is called multiple times
    // one `enter` but multiple `leave`

    dispatch_group_leave(group);
}];

débogage via le groupe de dispatch_ count

Sur le EXC_BAD_INSTRUCTION, vous devriez avoir accès à votre dispatch_group dans le débogueur. Imprimez le groupe dispatch_group et vous verrez:

<OS_dispatch_group: group[0x60800008bf40] = { xrefcnt = 0x2, refcnt = 0x1, port = 0x0, count = -1, waiters = 0 }>

Quand vous voyez count = -1 indique que vous avez quitté le groupe dispatch_. Assurez-vous de dispatch_enter et dispatch_leave le groupe en paires.

5
répondu pkamb 2018-03-06 07:12:07

mon problème était que je créais des objets que je voulais stocker dans Unnsmutable dictionnaire mais je n'ai jamais initialisé le dictionnaire. Par conséquent, les objets ont été supprimés par la collecte des ordures et de briser plus tard. Vérifiez que vous avez au moins une référence forte aux objets avec lesquels vous interagissez.

3
répondu mihai 2014-09-22 21:53:02

Dans mon cas:

PHImageRequestOptions *requestOptions = [PHImageRequestOptions new];
requestOptions.synchronous            = NO;

essayait de le faire avec dispatch_group

1
répondu Zaporozhchenko Aleksandr 2015-11-27 10:46:41

Parfois, tout ce qu'il faut pour obtenir un EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) manque un return déclaration.

Il a certainement été mon cas.

1
répondu Gabriel 2018-05-04 15:18:07

j'ai atterri ici à cause d'un XCTestCase, dans lequel j'ai désactivé la plupart des tests en les préfixant par " no_ " comme dans no_testBackgroundAdding. Une fois que j'ai remarqué que la plupart des réponses avaient quelque chose à voir avec les serrures et le threading, j'ai réalisé que le test contenait quelques exemples de XCTestExpectation avec des attenteforexpectations correspondantes. Ils étaient tous dans les tests pour handicapés, mais apparemment Xcode les évaluait encore à un certain niveau.

a la fin j'ai trouvé une XCTestExpectation cela a été défini comme @propriété mais manquait @synthétiser. Une fois que j'ai ajouté la directive synthize, L'instruction EXC_BAD_ a disparu.

0
répondu Elise van Looij 2017-06-13 14:14:18

Mon problème était que c'était dans mon init(). Probablement le "faible" l'a tué alors que l'init n'était pas terminé. Je l'ai déplacée de l'intérieur et ça a résolu mon problème.

0
répondu Yaron Abramovich 2018-07-24 07:16:57