"format string is not a string literal" dans une NSAlert : comment faire ?

colas_colas_ Membre
janvier 2014 modifié dans API AppKit #1

Bonjour j'ai un un warning 



"format string is not a string literal"

(qui ne produit pas d'erreur) sur les lignes suivantes :



 NSString * auxText ;
        auxText = [NSString stringWithFormat:@Test %@", aString];
        
        NSAlert * myAlert ;
        myAlert = [NSAlert alertWithMessageText:mainText
                                  defaultButton:@OK
                                alternateButton:nil
                                    otherButton:nil
                      informativeTextWithFormat:auxText] ;

J'ai le même warning dans un cas un peu plus subtil :



- (NSString *)someText:(BOOL)aBool
{
       NSMutableString * result = [@"" mutableCopy] ;

       (...)

       NSString * tempString = [NSString stringWithFormat:...] ;

       (...)

       [result appendString:tempString] ;
}

- (void)myMethod
{
(...)
    NSAlert * myAlert ;
    myAlert = [NSAlert alertWithMessageText:mainText
                              defaultButton:@OK
                            alternateButton:@Annuler
                                otherButton:nil
                  informativeTextWithFormat:[self someText:YES]] ;
(...)
}

J'imagine que vous avez déjà  rencontré ce warning.


Peut-on supprimer le warning tout en gardant la factorisation ?


 


Et vous, que faites-vous ? (J'ai lu ici qu'il est bien de garder son projet à  0 warning. J'en ai 44 et je vais essayer des les supprimer !)

Réponses

  • Regarde dans les options de compilation si tu as un truc du genre: -Wformat-nonliteral


     


    Extrait de la doc GCC 4.7:



     


     



    -Wformat

    Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense. This includes standard functions, and others specified by format attributes (see Function Attributes), in the printf, scanf, strftime andstrfmon (an X/Open extension, not in the C standard) families (or other target-specific families). Which functions are checked without format attributes having been specified depends on the standard version selected, and such checks of functions without the attribute specified are disabled by -ffreestanding or -fno-builtin.

    The formats are checked against the format features supported by GNU libc version 2.2. These include all ISO C90 and C99 features, as well as features from the Single Unix Specification and some BSD and GNU extensions. Other library implementations may not support all these features; GCC does not support warning about features that go beyond a particular library's limitations. However, if -pedantic is used with -Wformat, warnings will be given about format features not in the selected standard version (but not for strfmon formats, since those are not in any version of the C standard). See Options Controlling C Dialect.


    Since -Wformat also checks for null format arguments for several functions, -Wformat also implies -Wnonnull.


    -Wformat is included in -Wall. For more control over some aspects of format checking, the options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, and -Wformat=2 are available, but are not included in -Wall. 





  • Bonjour j'ai un un warning 


    "format string is not a string literal"

    (qui ne produit pas d'erreur) sur les lignes suivantes :



     NSString * auxText ;
            auxText = [NSString stringWithFormat:@Test %@", aString];
            
            NSAlert * myAlert ;
            myAlert = [NSAlert alertWithMessageText:mainText
                                      defaultButton:@OK
                                    alternateButton:nil
                                        otherButton:nil
                          informativeTextWithFormat:auxText] ;

    J'ai le même warning dans un cas un peu plus subtil :



    - (NSString *)someText:(BOOL)aBool
    {
           NSMutableString * result = [@"" mutableCopy] ;

           (...)

           NSString * tempString = [NSString stringWithFormat:...] ;

           (...)

           [result appendString:tempString] ;
    }

    - (void)myMethod
    {
    (...)
        NSAlert * myAlert ;
        myAlert = [NSAlert alertWithMessageText:mainText
                                  defaultButton:@OK
                                alternateButton:@Annuler
                                    otherButton:nil
                      informativeTextWithFormat:[self someText:YES]] ;
    (...)
    }

    J'imagine que vous avez déjà  rencontré ce warning.


    Peut-on supprimer le warning tout en gardant la factorisation ?


     


    Et vous, que faites-vous ? (J'ai lu ici qu'il est bien de garder son projet à  0 warning. J'en ai 44 et je vais essayer des les supprimer !)




     


     informativeTextWithFormat:@%@",auxText] ;


  •  


     


    informativeTextWithFormat:@%@",auxText] ;

     


    ça marche, mais je trouve ça vachement moins clair (et pas très joli).


     


    Est-ce préférable de faire comme tu dis pour d'autres raisons (plus de robustesse) ?


     


    Merci !


  • mpergandmpergand Membre
    janvier 2014 modifié #5

    C'est un waning optionnel du compilateur, supprime-le et tu n'auras plus ce message.


     


    Le but est d'éviter un plantage possible dans la forme:


    NSLog(str);


    si str contient des arguments de la forme %xx


     


    écrire NSLog(@%@",str) éllimine ce problème.


  • AliGatorAliGator Membre, Modérateur
    janvier 2014 modifié #6
    Ah non ne le supprime pas pour moi il est important ce warning et pas anodin.


    Si [self someText:YES] retourne une chaà®ne qui par hasard contient un token de format genre "%@ ou %d" ou "%.H" ou autre n'importe où dans cette string, plantage assuré. C'est ce dont parle mpergand sauf que ce problème n'est pas limité aux NSLog mais à  toutes les méthodes qui prennent un format + nombre variable d'arguments en paramètres.


    Le warning est explicite : ce qui est attendu est une chaà®ne de format, contenant des placeholders, et que tu fera suivre d'arguments. Donc c'est ça que tu dois donner et pas directement la chaà®ne elle même.


    Donc la bonne solution est celle de devulder. Il n'est acceptable d'ignorer ce warning que si [self someText:YES] était une méthode faite exprès pour retourner une chaà®ne de format, contenant toujours les mêmes placeholders dans le même ordre de picking (par exemple "%d - %f" ou "%d + %f" ou le plus subtil "%2$f - %1$d" selon les paramètres d'entrée mais que au moins y' ait toujours un placeholders %d correspondant au premier paramètre et %f pour le 2 eme). Cas d'usage qui est quand même assez rare.
Connectez-vous ou Inscrivez-vous pour répondre.