2010-08-21 11 views
3

J'ai un problème étrange. J'utilise une méthode des frameworks privés d'Apple dans mon application. Quand je l'appelle pour la première fois, ça marche. Quand je l'appelle pour la deuxième fois immédiatement sans rien entre les deux, il se bloque. Cependant, si je mets NSLog entre les deux appels, cela fonctionne à merveille. J'essaie donc de supprimer NSLog et de mettre entre-elles les boucles for-loops, sleep(), printf ("...") et fprintf (stderr, "...") pour émuler NSLog, mais cela n'aide pas. Je me demande comment la méthode sait que j'utilise NSLog? En d'autres termes, que fait réellement NSLog pour affecter les comportements de la méthode?Que fait réellement NSLog?

Merci beaucoup!

EDIT:

me semble résoudre ce problème. Je vais partager ma solution ici et j'espère que cela pourra être utile à certaines personnes.

Je crée une application multitouch utilisant MultitouchSupport.framework. J'ai copié le code de http://aladino.dmi.unict.it/?a=multitouch et ajouté un CFRelease à la fin de la boucle. Donc, au fond, ma principale méthode ressemble à ceci:

int main(void) { 
    int i; 
    NSMutableArray* deviceList = (NSMutableArray*)MTDeviceCreateList(); //grab our device list 
    for(i = 0; i<[deviceList count]; i++) { //iterate available devices 
     MTRegisterContactFrameCallback([deviceList objectAtIndex:i], touchCallback); //assign callback for device 
     MTDeviceStart([deviceList objectAtIndex:i], 0); //start sending events 
    } 
    CFRelease((CFMutableArrayRef)deviceList); 
    printf("Ctrl-C to abort\n"); 
    sleep(-1); 
    return 0; 
} 

Après avoir exécuté pendant un certain temps, il affichera « signal reçu programme: « EXC_BAD_ACCESS ». » Et voici la trace de la pile:

#0 0x7fff8795496e in ParsedMultitouchFrameRepInitialize 
#1 0x7fff879565b1 in mt_HandleMultitouchFrame 
#2 0x7fff87955a03 in mt_DequeueDataFromDriver 
#3 0x7fff87955b29 in mt_DequeueMultitouchDataFromDriverThreadEntry 
#4 0x7fff831b3456 in _pthread_start 
#5 0x7fff831b3309 in thread_start 

Cependant, il ne plantera pas si je mets NSLog ci-dessous MTDeviceStart.

La raison pour laquelle j'ai ajouté CFRelease((CFMutableArrayRef)deviceList) au code original est que je pense que les objets créés à partir de fonctions nommées * Create * ou * Copy * doivent être libérés par nous-mêmes. Mais il s'avère que si je le supprime comme le fait le code original, il ne tombera pas en panne, même sans utiliser NSLog. Donc, c'est peut-être parce que je publie deviceList trop tôt? Mais si c'est le cas, pourquoi NSLog semble-t-il capable d'empêcher le crash?

+5

Cela n'a probablement rien à voir avec le NSLog. Je posterais du code. –

+0

Veuillez modifier le code et la trace de la pile dans votre question. –

+0

Vous avez raison au sujet de la convention de nommage, mais puisque 'MTDeviceCreateList' est une fonction privée, il peut y avoir violation/non-conformité. (Cela signifie peut-être "créer le tableau de périphériques qui est destiné à rester actif pendant toute la durée du processus et le renvoyer".) Essayez d'exécuter votre programme (avec crash) sous Instrument Zombies d'Instruments. Avec cela, vous devriez être en mesure de prouver si votre version est une version supérieure, ou autrement déterminer la véritable cause de l'accident. –

Répondre

0

Il pourrait y avoir un problème avec la gestion de la mémoire: une version étrangère peut-être. Si vous postez le retraçage, il peut être utile de dépister le problème. (En fait, quelqu'un sur Twitter que j'ai suivi a mentionné quelque chose comme ça la nuit dernière).

+0

Wow! Merci beaucoup. J'ai essayé d'enlever un CFRelease de mon code, et cela fonctionne maintenant parfaitement. Je ne suis pas sûr de savoir pourquoi. Je viens d'ajouter mon code dans ma question. – ifvc

+0

Attention: si elle était diffusée trop tôt, mais qu'elle devait être finalement libérée, cela signifie que maintenant elle ne se bloque pas mais fuit à la place (c'est-à-dire, si c'était un problème de timing et que le début) –

1

Cela prend beaucoup de temps. Je ne suis pas sûr pourquoi. Il imprime la date et l'heure, le nom du processus, l'ID du processus, l'ID du thread et (enfin) la chaîne que vous avez demandée. I pense il envoie également le message de journal à syslogd (console Xcode ou iPCU montre multilignes NSLogs comme une seule entrée, je ne sais pas); l'IPC pourrait être significatif.

Essayez d'utiliser syslog() (#import <syslog.h> puis syslog(LOG_INFO, "Hello there!");, si cela fonctionne, mais vous obtenez pas de sortie, essayez de changer la priorité (voir man 3 syslog)

+0

Oui, NSLog envoie le message à ASL, le même que syslog. Je ne suis pas sûr de ce que vous attendez de syslog à faire différemment, mais ne l'imprimez pas sur stderr? –

+0

Je répondais "si je mets NSLog entre les deux appels, ça marche", ce qui suggère que syslog() pourrait faire certaines choses que NSLog fait pour le faire "travailler". –

2

Quelque chose de semblable à ceci:.

static inline void NSLogMessageString(NSString *string){ 
    NSString *date=[[NSDate date] 
    descriptionWithCalendarFormat:@"%Y-%m-%d %H:%M:%S.%F" 
         timeZone:nil locale:nil]; 
    NSString *process=[[NSProcessInfo processInfo] processName]; 

    NSLogFormat(@"%@ %@[%d:%lx] %@",date,process,NSPlatformProcessID(),NSPlatformThreadID(),string); 
} 

void NSLogv(NSString *format,va_list arguments) { 
    NSString *string=NSStringNewWithFormat(format,nil,arguments,NULL); 

    NSLogMessageString(string); 

[string release]; 
} 

void NSLog(NSString *format,...) { 
    va_list arguments; 

    va_start(arguments,format); 

    NSLogv(format,arguments); 
} 

Merci pour poser cette question lol, je voulais la réécrire afin que je puisse ajouter des variables de débogage, ce qui signifie que je pourrais désactiver tous les appels NSLogging lorsque nécessaire.

+0

- Trouvé dans NSObjcRuntime –

1

NSLog peut affecter des problèmes comme celui que vous exécutez int o parce que cela affecte l'ordre d'exécution des threads car lorsque vous appelez NSLog dans un thread d'arrière-plan, il doit avoir un accès exclusif à stdout.Le débogage de printf avec des problèmes de threads conduit souvent à des "heisenbugs" pour cette raison (c'est-à-dire qu'ils changent de comportement quand vous essayez de les examiner).