Début sous Xcode 4.2

tabliertablier Membre
J'ai enfin acheté Lion et chargé Xcode 4.
Donc j'essaie de comprendre ce truc!
Je fais l'analyse d'un projet passé sous  Xcode 4 et j'aimerais bien qu'on m'explique pourquoi j'obtiens l'information que la valeur de l'argument n'est pas initialisé?
La macro suivante est définie dans le .pch, donc valable pour l'ensemble du projet
et dans les méthodes ou j'utilise la macro j'obtiens:
- (IBAction)a_v3upgr:(id)sender // clic sur le bouton mise à  jour
{
NSString *tic8;

v3upgrd = [o_v3upgrd indexOfSelectedItem] ;
switch (modesn) {
case mFi: switch (v3upgrd) {
case asorigin: tic8 = @fsntr08 ; break ;
case xibupgrd: tic8 = @fsntr09 ; break ;
case nibcompi: tic8 = @fsntr0A ; break ;
case nibredui: tic8 = @fsntr0B ; break ;
case nibedite: tic8 = @fsntr0C ; break ; } ; break;
case mDo: switch (v3upgrd) {
case asorigin: tic8 = @dsntr08 ; break ;
case xibupgrd: tic8 = @dsntr09 ; break ;
case nibcompi: tic8 = @dsntr0A ; break ;
case nibredui: tic8 = @dsntr0B ; break ;
case nibedite: tic8 = @dsntr0C ; break ; } ; break;
case mPr: switch (v3upgrd) {
case asorigin: tic8 = @psntr08 ; break ;
case xibupgrd: tic8 = @psntr09 ; break ;
case nibcompi: tic8 = @psntr0A ; break ;
case nibredui: tic8 = @psntr0B ; break ;
case nibedite: tic8 = @psntr0C ; break ; } ; break;
} ;

[o_snTitr08 setStringValue:localiser(tic8)] ;      argument in message expression is an uninitialized value
}

Réponses

  • AliGatorAliGator Membre, Modérateur
    02:09 modifié #2
    Parce que rien ne garantis que tu passes dans un des "case" de tes switch/case.
    Tu n'as pas de "default:" dans tes switch, et il se peut que " même si d'un point de vue métier tu penses que ça n'arrivera jamais mais ça le compilateur ne peux pas le deviner " tu tombes donc sur un cas d'une combinaison { [tt]modesn[/tt] / [tt]v3upgrd[/tt] } qui ne colle avec aucun de tes cas.

    Dans ce cas là , tic8 ne sera alors pas initialisé (puisque tu l'as déclaré au début mais sans lui donner de valeur), d'où le warning.

    NB : Je me demande si, quand tu build avec "Analyse" (analyse statique Clang) et que tu cliques ensuite sur le warning il ne t'indique pas le cas qu'il a suivi (quelles branches de tes switch, en l'occurrence aucune de celles existantes) pour t'expliquer mieux l'erreur ?

    En tout cas la solution est simple : initialiser tic8 avec une valeur par défaut (même [tt]nil[/tt]) au cas où tu ne passes dans aucun de tes switch/case imbriqués.
  • tabliertablier Membre
    02:09 modifié #3
    Ok, merci! Je vais reprendre l'ensemble du code pour corriger cela!
    J'ai d'autres problèmes, mais il fait que je les cerne mieux avant d'en parler.

      :p   :p   <3   <3   :p   :p   hipss!!
  • tabliertablier Membre
    janvier 2012 modifié #4
    Encore des erreurs incompréhensibles qui ne sont pas reportées sous 3.2.6 mais le sont sous Xcode 4.2!
    - (NSString *)traite1fichier:(NSString *)command
    {
    NSString *erreur, *leplist ;
    NSMutableString *letext ;
    NSMutableArray *hierarh ;
    NSInteger k ;

    letext = [NSMutableString stringWithCapacity:2048] ;
    hierarh = [NSMutableArray arrayWithCapacity:30] ;
    ............................................. etc
    [leTout removeAllObjects] ;
    [leTout setDictionary:[NSDictionary dictionaryWithContentsOfFile:leplist]] ; // prise du dictionnaire globale
    ............................................. etc
    [hierarh setArray:[leTout objectForKey:ns_clef_hie]] ; // pointe la hiérarchie

    for (k=[hierarh count]-1 ; k>=0 ; k--)
    { if ([[[hierarh objectAtIndex:k] valueForKey:ns_ObjId] intValue] < 0 )
    [hierarh removeObjectAtIndex:k] ; } ;

    [self iterer:hierarh level:0] ;                // traite la hiérarchie (récursif) cet appel provoque l'erreur!

    [gestion removeItemAtPath:leplist error:NULL] ; // supprime le fichier
    [fihSort writeToFile:pathStrings atomically:NO] ;
    return @";" ; // pas d'erreur
    }


    // itérations dans un objet
    // nivo d'imbrication
    // retourne le nombre de strings sortis.
    //
    - (long)iterer:(NSMutableArray *)top level:(NSInteger)nivo
    {
    NSInteger x, k, kmax, knt, strLoc, strNivo ;
    NSMutableString *entet ;
    NSString *ObjTmp, *stra ;
    NSDictionary *dicoObj, *dicoItem ;
    NSMutableArray *contenu ;
    long taille0, taille1 ;

    entet = [NSMutableString stringWithCapacity:50] ;
    contenu  = [NSMutableArray arrayWithCapacity:30] ;
    [entet setString:@";"] ;
    strLoc = 0 ; // nbr string localisable
    ................................................... etc
    les erreurs obtenues lors de l'appel de "iterer" sont:
    2012-01-04 14:53:45.316 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100040700
    2012-01-04 14:53:45.357 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100040700
    2012-01-04 14:53:45.387 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100041060
    2012-01-04 14:53:45.415 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100041060
    L'argument de "iterer" est un NSMutableArray. je ne vois pas ou est (sont) le(s) constanteString qui donne(nt) ces erreurs!
  • CéroceCéroce Membre, Modérateur
    02:09 modifié #5
    C'est probablement un problème d'objet désalloué.
  • tabliertablier Membre
    02:09 modifié #6
    J'ai un peu des doutes sur la dés-allocation d'un objet: L'objet qui contient ces méthodes est instancié par IB et donc ne sera pas dés-alloué avant la fin du programme. L'objet "hierarh" est instancié par un constructeur de facilité et donc se trouve sur une zone d'auto-release. Pourquoi serait-il dés-alloué tant que je m'en serts?
    Est-ce que je dis des bétises?
  • AliGatorAliGator Membre, Modérateur
    janvier 2012 modifié #7
    dans 1325699764:

    J'ai un peu des doutes sur la dés-allocation d'un objet: L'objet qui contient ces méthodes est instancié par IB et donc ne sera pas dés-alloué avant la fin du programme.
    Heu pardon ?

    1) Les objets à  la racine d'un fichier XIB ont une politique de gestion mémoire différente sous OSX et sous iOS, attention (cf le Resources Programming Guide et la partie sur la gestion mémoire du cycle de vie des objets d'un XIB)

    2) Du coup j'espère que tu as une [tt]@property(retain)[/tt] sur tes Top-Level-Objects de ton XIB pour être sûr qu'il n'est pas autorelease et détruit à  la fin de l'itération de la RunLoop dans laquelle le XIB a été chargé

    3) Sous OSX on a souvent qu'un MainMenu.xib et on se fout un peu de la mémoire que ça prend de tout charger d'un coup. Sous iOS c'est bien différent, on fait du lazy-loading et on ne charge les XIB que lorsque c'est nécessaire (usage typique : les UIViewControllers qui ont un XIB associé qu'ils ne chargent que quand l'écran demande à  être affiché). Et surtout, iOS reçoit une alerte mémoire, si la vue du ViewController n'est plus à  l'écran à  cet instant, le contenu du XIB est totalement déchargé, la méthode [tt]viewDidUnload[/tt] est appellée pour qu'on fasse le ménage, et le XIB est rechargé plus tard quand il y aura de nouveau de la mémoire et surtout que la vue devra être réaffichée à  l'écran (mais tant qu'elle n'a pas à  être réaffichée, principe de lazy-loading, on va pas s'embêter à  re-désarchiver le XIB)

    Bref vu que tu as posté dans la section commune je sais pas si tu codes pour iOS ou pour OSX mais ton affirmation me semble bien dangereuse quand même...
  • tabliertablier Membre
    janvier 2012 modifié #8
    Je ne développe que sous OSx, jamais sous IOS, et je n'ai qu'un seul MainMenu.xib (chargé automatiquement au lancement).
    Les variables d'instance que je veux conserver sont initialisée et reçoivent systématiquement un retain. Ce sont généralement des "Mutables".
    Je vais lire l'article que tu conseilles. Mais je pense que dans le cas qui m'occupe, le problème n'est pas une dés-allocation.


    Nota, je suggère que l'on supprime la section commune. Dans cette section les posts sont en majorité liés à  IOS. Ce qui fait que je ne sais jamais ce que je lis!!
  • mpergandmpergand Membre
    02:09 modifié #9
    Citation
    2012-01-04 14:53:45.316 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100040700
    2012-01-04 14:53:45.357 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100040700
    2012-01-04 14:53:45.387 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100041060
    2012-01-04 14:53:45.415 Localise[829:403] -[__NSCFConstantString count]: unrecognized selector sent to instance 0x100041060

    L'argument de "iterer" est un NSMutableArray. je ne vois pas ou est (sont) le(s) constanteString qui donne(nt) ces erreurs!


    ajoute un breakpoint sur -[NSException raise]
    cela devrait te permettre de connaà®tre d'objet responsable de l'erreur.
  • CéroceCéroce Membre, Modérateur
    02:09 modifié #10
    Ce n'est qu'une supposition de ma part par rapport aux symptômes décrits. J'ai déjà  vu ce genre de choses et des désallocation prématurées en était la cause.
  • tabliertablier Membre
    02:09 modifié #11
    C'est probablement un problème d'objet désalloué.
    en définitive c'est probable car Si je remplace l'appel
    [self iterer:hierarh level:0] ;
    par
    [self iterer:[NSArray arrayWithArray:hierarh] level:0] ;
    les erreurs disparaissent. Donc le principe du C qui veut qu'une variable déclarée en local dans un procédure reste jusqu'à  la sortie de la procédure ne marches pas dans une méthode Objective-C?
    J'ai tout faux?
  • zoczoc Membre
    02:09 modifié #12
    dans 1325715525:

    Donc le principe du C qui veut qu'une variable déclarée en local dans un procédure reste jusqu'à  la sortie de la procédure ne marches pas dans une méthode Objective-C?

    Bah si, et heureusement !

  • CéroceCéroce Membre, Modérateur
    02:09 modifié #13
    [arrayWithArray:hierarh] crée une nouvelle instance de NSArray qui sera autoreleasée au prochain cycle. L'instance va donc survivre un cycle de plus que hierarh s'il est lui aussi autoreleasé.
  • cyranocyrano Membre
    02:09 modifié #14
    oulala.

    c'est du charabia....

    tu as une erreur, point de supposition foireuse,

    mets des logs, des asserts, des breakpoints....

    et puis tu passes un NSArray quand il faut un NSMutableArray et le compilo ne rale pas??????

    [self iterer:[NSArray arrayWithArray:hierarh] level:0] ;
    .../...
    - (long)iterer:(NSMutableArray *)top level:(NSInteger)nivo
  • zoczoc Membre
    janvier 2012 modifié #15
    dans 1325749946:

    [arrayWithArray:hierarh] crée une nouvelle instance de NSArray qui sera autoreleasée au prochain cycle. L'instance va donc survivre un cycle de plus que hierarh s'il est lui aussi autoreleasé.

    Euuuh, il n'y a pas de retour à  la RunLoop dans son code, donc aucun drainage de quelque autorelease pool que ce soit...
  • CéroceCéroce Membre, Modérateur
    02:09 modifié #16
    dans 1325784148:

    Euuuh, il n'y a pas de retour à  la RunLoop dans son code (ou alors il est dans la fonction récursive qui n'a pas été divulguée en entier), donc aucun drainage de quelque autorelease pool que ce soit...

    Euh, oui exact, là  c'est moi qui divague.
    Ce que j'en dis moi, c'est que tout ça mérite un bon coup d'analyse statique et d'Instruments/NSZombie.
  • tabliertablier Membre
    janvier 2012 modifié #17
    SVP, Pas sur la tête avec le clavier! merci!  (je ne suis pas informaticien) 

    tu as une erreur, point de supposition foireuse
    Là , je suis d'accord, il y a une erreur quelque part et/ou une méconnaissance de quelque chose à  propos des variables locales! J'avais mis des BrkPt sur l'appel de iterer et sur la première ligne exécutable dans iterer. L'état des variables parait normal, je n'en ai donc rien tiré.
    et puis tu passes un NSArray quand il faut un NSMutableArray et le compilo ne rale pas?
    Non, lorsque je modifie l'argument en NSArray, je corrige aussi les déclarations pour que ça corresponde. Simplement je n'ai pas explicité la chose dans mon dernier post pour ne pas gonfler le texte.

    Après modifications, le programme marche sous Lion.
    Je ne fais pas explicitement de retour à  la runloop ni de drainage. Et je ne comprends pas pourquoi ce retour aurait lieu durant un appel de méthode. Je crée un autorelease pool pour l'ensemble du travail d'extraction, puis je le supprime avant de retourner au contrôle principale de l'application. Pour info, vous avez la totalité de l'implémentation en pièce jointe (.zip).

    Ce que j'ai trouvé sous Lion: le comportement des méthodes n'est pas forcément le même que sous SnowLeopard.
    10.6.8 ->  Xcode 3.2.6, SDK 10.6 compilateur "LLVM GCC 4.2"
    10.7.2 ->  Xcode 4.2.1, SDK 10.6 compilateur "apple LLVM compiler 3.0"
    deux exemples:
    [newLang setString:v1lang stringByDeletingPathExtension] stringByAppendingPathExtension:@&quot;lproj&quot;;
      10.6.8:  jamais d'erreur (compilation et exécution) même si *v1lang = @";"
      10.7.2:  erreur à  l'exécution si *v1lang = @";" ->  impossible d'ajouter une extension à  un string vide.

    ObjTmp = [[dicoItem objectForKey:@object-id] stringValue] ;      // prise identifiant dans le dictionnaire.
      10.6.8:  jamais d'erreur (compilation et exécution)
      10.7.2:  erreur systématique à  l'exécution ->  __NSCFConstanteString  sélecteur non reconnu.
    Donc, le comportement par défaut d'une méthode peut changer entre deux versions du système, du compilateur ou de ?????  ( complétez vous-même).
  • cyranocyrano Membre
    janvier 2012 modifié #18
    dans 1325791425:

    Donc, le comportement par défaut d'une méthode peut changer entre deux versions du système, du compilateur ou de ?????  ( complétez vous-même).


    oui, cela arrive très souvent avec un comportement indéfini, même si en l'état ton programme fonctionne il y a un bug.

    un conseil;
    décompose tes lignes de code en ligne simple (une action par ligne). tu trouveras l'action qui buge et peut être la raison.

    Question:
    un fichier sans nom avec une extension est t'il permis?

    Courage. (contourner un bug n'est pas une bonne soluce)

    PS: je ne suis pas informaticien non plus. ce n'est pas une tare  :D


  • zoczoc Membre
    02:09 modifié #19
    dans 1325791425:
    Donc, le comportement par défaut d'une méthode peut changer entre deux versions du système

    En général non, et dans les cas particuliers ce changement de comportement est systématiquement documenté. Ce n'est clairement pas le cas des messages qui posent problème



    du compilateur

    Non, sauf bug du compilateur, toujours possible, surtout avec clang vu sa relative jeunesse.

  • tabliertablier Membre
    02:09 modifié #20
    Ma réponse va être courte. Pour avoir le même string résultat il faut écrire:
    (ObjTmp est un NSString et dicoItem un dictionnaire obtenu avec ibtool)
    sous 10.6.8  ObjTmp = [[dicoItem objectForKey:@object-id] stringValue] ;
    sous 10.7.2  ObjTmp = [dicoItem objectForKey:@object-id] ;

    si j'écris:
    sous 10.6.8  ObjTmp = [dicoItem objectForKey:@object-id] ;
    sous 10.7.2  ObjTmp = [[dicoItem objectForKey:@object-id] stringValue] ;

    J'obtiens une erreur dans les deux cas et je ne m'explique pas la chose!
  • zoczoc Membre
    02:09 modifié #21
    dans 1325957330:

    Ma réponse va être courte.

    Alors ma question va être simple. Quel est le type réel des objets contenus dans le dictionnaire ?

  • tabliertablier Membre
    02:09 modifié #22
    Ce devrait être identique puisque c'est la même commande d'ibtool  sur le même nib, mais tu as raison, c'est à  vérifier!
    Cela me demande deux vérifications. Une sous 10.6.8 et une sous 10.7.2.
  • tabliertablier Membre
    janvier 2012 modifié #23
    @zoc
    Ta question est très bonne et je suis assez étonné. ibtool 3.2.6 et ibtool 4.2.1 ne génèrent pas le même fichier .plist malgré des "man" presque identiques et de même date (aug 15 2008)!!! voici les deux extraits:
    ibtool 3.2.6
    <key>name</key>
    <string>WorkingArea</string>
    <key>object-id</key>
    <integer>6</integer>
    </dict>
    ibtool 4.2.1
    <key>name</key>
    <string>WorkingArea</string>
    <key>object-id</key>
    <string>6</string>
    </dict>
    Là  je suis trompé par une identité apparente entre les deux ibtool. Donc désolé, j'ai dit une bétise et après vérifications, seuls les "object-id" ont changés de type de valeur dans le .plist.
Connectez-vous ou Inscrivez-vous pour répondre.