Bug avec NSScanner (peut-être!)

tabliertablier Membre
01:18 modifié dans Vos applications #1
Je n'y comprends rien!!
dans un petit développement, j'obtiens une erreur "EXC_BAD_ACCESS" chaque fois que j'utilise un NSScanner!
En gros, je remplis un NSArray "laBdData" de NSDictionary en utilisant les données contenues dans un .csv. J'ai un dictionnaire pour chaque ligne du .csv.  J'ai 2 boucles imbriquées: Une pour les lignes avec à  l'intérieur une pour les champs de la ligne.
Dans la boucle des champs, j'appelle la méthode ci dessous qui remplit un objet du dictionnaire courant:
<br />- (void)metUnChamps:(NSString *)schamps :(int)indx :(NSMutableDictionary *)dicoFilm :(int)nbrDigt :(BOOL)rfnum<br />{<br />int		&nbsp; &nbsp;  lentier, faire ;<br />NSString	*theKey ;<br />NSScanner&nbsp; &nbsp;  *leScan	;<br /><br />	theKey = [NSString stringWithUTF8String:clefxec[lordre[indx]].clef] ;		// le nom du champs<br />	faire&nbsp; = clefxec[lordre[indx]].exec ;										// le traitement à  faire.<br /><br />	switch (faire) { <br />	case&nbsp; kstring:	[dicoFilm setValue:schamps forKey:theKey] ;					// texte<br />					break ;	<br />	case&nbsp; kinteger:	if ([schamps length] == 0)									// integer<br />						lentier = 0 ;<br />					else<br />					 {	leScan = [NSScanner localizedScannerWithString:schamps] ;<br />						if ( ![leScan scanInt:&amp;lentier ]) lentier = 0 ;			// pas de valeur -&gt; 0<br />					 } ;														// <br />					[dicoFilm setValue:[NSNumber numberWithInt:lentier] forKey:theKey] ;	// integer <br />					break ;<br />	case&nbsp; kreal:	break ;														// valeur flottante					<br />	case&nbsp; krefr:	break ;														// références<br />	case&nbsp; kjaqet:	break ;														// non programmé<br />	case&nbsp; karray:	break ;														// non programmé	<br />		default :	break ;<br />	} ;<br />}

tout se passe bien, le résultat (l'array "laBdData") est sauvé sous forme de plist par:
laBdData writeToFile:leModel atomically:YES] ;

et le controle à  postériori montre que le fichier est correct et contient les bonnes données. Jusque là  tout est conforme à  ce que j'attends.

MAIS, quelque soit l'action suivante que je demande (clic dans le GUI) le programme plante avec l'erreur sus-dite!!

Par contre, si je remplace le case kinteger: ci-dessus par:
case&nbsp; kinteger:	lentier = 0 ;<br />			break ;

alors je lis des csv ou sauve des fichiers à  la chaine et sans erreur!!

Je lis et relis la doc sur la gestion de la mémoire et sur NSScanner et je ne trouve (ou comprend) rien!
1) quelqu'un aurait une idée.
2) Comment débugguer ce type d'erreur et avec quoi?

(si nécessaire, je peux mettre le projet complet sur un prochain post.)

Réponses

  • psychoh13psychoh13 Mothership Developer Membre
    01:18 modifié #2
    J'aime le nom de ta méthode, super explicite : metsUnCamps::::: ???

    Ton code est super crade et pas très clair...

    Ensuite, ton erreur doit sans doute venir du fait que tu ne fais pas de retain sur des objets que tu conservent au-delà  de la fin de la méthode...
  • BruBru Membre
    01:18 modifié #3
    Pour pister le problème, pas de miracle : faut faire tourner le projet dans Xcode en mode debug (ou development), puis reproduire le plantage.
    En debug, GDB va prendre le relais et t'afficher la liste des dernières méthodes obj-c appelées (dans la liste "Thread"). La dernière (la plus haute dans la liste) est vraissemblablement la plantogène.
    Ne te reste plus alors à  coup de NSLog/point d'arrêt de voir ce qui se passe (notamment voir si les paramètres transmis sont corrects).

    .
  • tabliertablier Membre
    01:18 modifié #4
    C'est vrai que sur le site, ma méthode n'apparait pas correctement. Le copier-coller entre mon projet et l'éditeur de post, perd les couleurs et n'a pas la même dimension pour les "Tab"! Grrr!  Mais tout réécrire dans le post! ouuuuille!. D'autre part, j'ai une tendance à  donner des noms de variables locales significatifs (pour moi , hélas) plus tot que d'allonger la signature des méthodes! d'ou les :::::

    Pour le retain, la seule chose que fait cette méthode est de modifier une valeur dans un dictionnaire. Si j'ai bien lu, le retain sur la valeur est automatique dans ce cas. D'autre part le plantage ne se produit que si j'utilise NSScanner pour initialiser la valeur. Si j'attribue une valeur arbitraire (lentier = 25; par exemple) le programme ne plante pas!

    Je suis le déroulement du programme sous GDB. Mais ce qui me gène c'est que le plantage ne se produit apparemment pas dans mon code. Il se produit lorsque je clique un bouton ou que je sélectionne "Quitter" dans le menu "Fichier". Je n'ai que 2 actions dans ce programme. Je mets des point d'arrêt sur la première ligne des 2 méthodes - (IBAction)...
    Je clique un bouton et le plantage se produit avant d'atteindre la méthode liée. Les quatres indications en haut de la liste des Threads sont:
    0  objc_msgSend_rtp
    1  CFDictionarySetValue
    2  synchroniseXMLDomain
    3  _CFPreferencesDomainSynchronise
    Le nom d'une de mes méthodes n'apparaà®t qu'en 13me position!
      Je reste dubitatif!.
  • tabliertablier Membre
    01:18 modifié #5
    J'ai trouvé!  Vos conseils étaient bons! à  tout les deux! 
    J'ai oublié le retain sur la ligne:  defauts = [NSUserDefaults standardUserDefaults] ;
    Et j'ai sauté la première vrai ligne pour mettre un point d'arrêt car jusqu'à  présent elle ne bugguait pas! Elle ne buggue que si l'on utilise dans le programme les userdefauts, ce qui est le cas de NSScanner qui utilise les "local" ou les "local" par défaut.
    (Ce n'est peut-être pas correcte, mais je n'initialise "defauts" qu'une seule fois au début de l'exécution)



Connectez-vous ou Inscrivez-vous pour répondre.