110 votes

Avertissement : "format n'est pas un littéral de chaîne et aucun argument de format"

Depuis la mise à jour vers la dernière version de Xcode 3.2.1 et Snow Leopard, je reçois l'avertissement suivant

"format n'est pas une chaîne littérale et aucun argument de format"

à partir du code suivant :

NSError *error = nil;

if (![self.managedObjectContext save:&error]) 
{
    NSLog([NSString stringWithFormat:@"%@ %@, %@", 
       errorMsgFormat, 
       error, 
       [error userInfo]]);      

}

Si errorMsgFormat est un NSString avec des spécificateurs de format (ex : "print me like this: %@" ), qu'est-ce qui ne va pas avec l'énoncé ci-dessus NSLog appel ? Et quelle est la méthode recommandée pour corriger le problème afin que l'avertissement ne soit pas généré ?

157voto

Jon Hess Points 10529

Xcode se plaint parce que c'est un problème de sécurité.

Voici un code similaire au vôtre :

NSString *nameFormat = @"%@ %@";
NSString *firstName = @"Jon";
NSString *lastName = @"Hess %@";
NSString *name = [NSString stringWithFormat:nameFormat, firstName, lastName];
NSLog(name);

Cette dernière instruction NSLog va exécuter l'équivalent de ceci :

NSLog(@"Jon Hess %@");

Cela va amener NSLog à chercher un argument de chaîne supplémentaire, mais il n'y en a pas. A cause de la façon dont le langage C fonctionne, il va prendre un pointeur aléatoire dans la pile et essayer de le traiter comme une NSString. Cela fera très probablement planter votre programme. Aujourd'hui, vos chaînes de caractères ne contiennent probablement pas de %@, mais un jour elles pourraient en contenir. Vous devriez toujours utiliser une chaîne de format avec des données que vous contrôlez explicitement comme premier argument des fonctions qui prennent des chaînes de format (printf, scanf, NSLog, -[NSString stringWithFormat :], ...).

Comme le souligne Otto, vous devriez probablement faire quelque chose comme :

NSLog(errorMsgFormat, error, [error userInfo]);

113voto

Sixten Otto Points 10267

Est-ce que vous imbriquez vos crochets correctement ? Je ne pense pas que NSLog() aime ne prendre qu'un seul argument, ce qui est ce que vous lui passez. En outre, il fait déjà le formatage pour vous. Pourquoi ne pas simplement faire ça ?

NSLog(@"%@ %@, %@", 
   errorMsgFormat, 
   error, 
   [error userInfo]);

Ou, puisque vous dites errorMsgFormat est une chaîne de format avec un seul caractère de remplacement, essayez-vous de faire cela ?

NSLog(@"%@, %@", [NSString stringWithFormat:errorMsgFormat, error], 
   [error userInfo]);

38voto

Alex Whittemore Points 421

Réponse finale : Comme l'a dit Jon Hess, il s'agit d'un problème de sécurité car vous passez une chaîne WHATEVER à une fonction qui attend une chaîne de format. C'est-à-dire qu'elle va évaluer tous les spécificateurs de format DANS la chaîne whatever. S'il n'y en a pas, c'est génial, mais s'il y en a, ça peut être grave.

La bonne chose à faire, alors, est d'UTILISER directement une chaîne de format, par exemple

NSLog(@"%@", myNSString);

De cette façon, même s'il y a des spécificateurs de format dans myNSString, ils ne sont pas évalués par NSLog.

13voto

Qrikko Points 99

Je ne recommande pas spécialement d'utiliser ceci, puisque l'avertissement EST un vrai avertissement dans une utilisation dynamique du langage, il est possible de faire des choses en cours d'exécution à la chaîne (c'est-à-dire insérer de nouvelles informations ou même planter le programme) Cependant, il est possible de forcer la suppression si vous SAVEZ que cela devrait être comme ça et que vous ne voulez vraiment pas être averti à ce sujet

#pragma GCC diagnostic ignored "-Wformat-security"

Indiquerait à GCC d'ignorer temporairement l'avertissement de compilation Encore une fois, cela ne résout rien, mais il peut y avoir des moments où vous ne pouvez pas trouver un bon moyen de résoudre le problème.

10voto

Martytoof Points 162

J'ai juste passé un nil pour annuler les avertissements, peut-être que cela fonctionnerait pour vous ?

NSLog(myString, nil) ;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X