2010-05-15 5 views
2

Visiteur fréquent mais premier message ici sur StackOverflow, j'espère que vous pourrez m'aider avec ça. Je suis assez nouveau à Obj-C et XCode, et je suis confronté à ce problème vraiment ... étrange .... Google n'a rien trouvé. Fondamentalement, j'obtiens un signal EXC_BAD_ACCESS sur une ligne qui ne fait pas de déréférencement ou quelque chose comme ça que je peux voir. Vous vous demandez si vous avez une idée de ce que vous cherchez. J'ai trouvé un travail autour, mais aucune idée pourquoi cela fonctionne ... La ligne la version cassée vomit sur est la ligne:EXC_BAD_ACCESS lorsque vous lancez simplement un pointeur dans Obj-C

LevelEntity *le = entity; 

où je reçois mon mauvais signal d'accès.

va ici:

CETTE VERSION TRAVAUX

NSArray *contacts = [self.body getContacts]; 
    for (PhysicsContact *contact in contacts) 
    { 
    PhysicsBody *otherBody; 
    if (contact.bodyA == self.body) 
    { 
    otherBody = contact.bodyB; 
    } 
    if (contact.bodyB == self.body) 
    { 
    otherBody = contact.bodyA; 
    } 

    id entity = [otherBody userData]; 
    if (entity != nil) 
    { 
    LevelEntity *le = entity; 

    CGPoint point = [contact contactPointOnBody:otherBody]; 
    } 
    } 

CETTE VERSION DOESNT TRAVAIL

NSArray *contacts = [self.body getContacts]; 
    for (NSUInteger i = 0; i < [contacts count]; i++) 
    { 
    PhysicsContact *contact = [contacts objectAtIndex:i]; 
    PhysicsBody *otherBody; 
    if (contact.bodyA == self.body) 
    { 
    otherBody = contact.bodyB; 
    } 
    if (contact.bodyB == self.body) 
    { 
    otherBody = contact.bodyA; 
    } 

    id entity = [otherBody userData]; 
    if (entity != nil) 
    { 
    LevelEntity *le = entity; 

    CGPoint point = [contact contactPointOnBody:otherBody]; 
    } 
    } 

Ici, le seulement La différence entre les deux exemples est la façon dont j'énumère à travers mon tableau. Dans la première version (qui fonctionne) j'utilise pour (... dans ...), où comme dans la seconde j'utilise pour (...; ...; ...). Autant que je puisse voir, ceux-ci devraient être les mêmes.

Cela me fait vraiment peur. Quelqu'un at-il une expérience similaire ou une idée de ce qui se passe ici? Ce serait vraiment génial :)

Cheers, Alex

+0

Juste curieux - dans cette ligne: CGPoint point = [contact contactPointOnBody: otherBody]; faites-vous quelque chose avec le point que vous avez supprimé de l'exemple de code, ou est-ce que cet appel définit réellement certains états en contact ou autre? –

+0

Je fais quelque chose avec ça maintenant - je n'étais pas au moment de l'écriture de l'échantillon, comme j'ai découvert le crash entre l'écriture de la ligne citée, et réellement faire quelque chose avec la valeur :) – AlexC

Répondre

3

Tout d'abord, si vous avez un accident, vous avez un backtrace. Fournissez toujours le backtrace avec votre question (ce sera dans le débogueur et peut être copié/collé). Comme l'indique implicitement Vojito, la cause la plus fréquente de tels accidents est liée à la sur-libération d'objets. Dans votre cas, for(;;) et for(... in ...) ne sont pas exactement les mêmes. Ce dernier est très susceptible de provoquer la conservation des objets dans le tableau pendant la durée de l'itération ou la libération automatique lors de la récupération (je dis "très probable" parce que je ne l'ai pas testé - mais cela expliquerait le comportement).

Dans votre code, vous modifiez votre graphe d'objet pendant l'itération avec des instructions telles que otherBody = contact.bodyB. Si l'une de ces instructions provoque la sortie d'un des éléments du tableau en cours de sortie sous le tableau, un incident se produit. De même, si la modification du graphe d'objet fait contact.bodyA ou contact.bodyB pour devenir une référence pendante, vous verrez un plantage.

Tout juste une supposition éclairée. Publiez le backtrace et, comme l'a suggéré Vojito, exécutez l'instrument Allocation dans Instruments avec détection de zombie activée.

+0

Hmm, merci, ça sonne comme ça soit ça. Il semble que j'ai encore beaucoup à apprendre sur la gestion de la mémoire! Je viens d'un arrière-plan C#, donc généralement je suis habitué à tout ce qui est pris en charge gratuitement. C'est intéressant, mais dur travail! – AlexC

1

Les variables de pile, y compris les références d'objet, ne s'initialiseront pas automatiquement à nil/0/NULL.Essayez de régler otherBody à zéro dans son initialiseur:

PhysicsBody *otherBody = nil; 

Si le débogueur dit que l'affectation est le où l'exception se produit, il peut effectivement être la déclaration au-dessus, à savoir [otherBody userData]. Sans l'initialiser, otherBody est une valeur de poubelle.

+0

S'il est vrai qu'il devrait initialiser otherBody à zéro, il ne le fait pas à la fois celui qui fonctionne et celui qui ne fonctionne pas, ce qui signifie que (en quelque sorte) ne semble pas causer le crash, sauf si NSFastEnumeration gagne avec la pile (que je ne crois pas) –

+0

Bon point, merci. Comme Jared P l'a déclaré, je ne crois pas que cela provoque l'accident, bien que, comme vous l'avez dit, il s'agit, en règle générale, d'une bonne pratique. Merci :) – AlexC

+0

Depuis NSFastEnumeration est impliqué, cela signifie que les piles sont complètement différentes entre les deux exemples. Ainsi, dans un cas, otherBody (en raison de la sémantique d'appel) ne peut jamais être corrompu et commencer avec une valeur nulle. @AlexChilcott, avez-vous essayé ma suggestion? De vos commentaires, il ne semble pas que vous ayez enquêté si cela le corrige (ou la proposition de la réponse acceptée). – Jason

Questions connexes