Depuis la mise à niveau vers le dernier Xcode 3.2.1 et Snow Leopard, j'ai reçu l'avertissement
"format pas un littéral de chaîne 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 (par exemple:) "print me like this: %@"
, quel est le problème avec l' NSLog
appel ci - dessus ? Et quelle est la méthode recommandée pour résoudre ce problème afin que l'avertissement ne soit pas généré?
la source
NSLog()
peut prendre un argument, lorsque la chaîne de format ne contient aucun spécificateur de format.Xcode se plaint car c'est un problème de sécurité.
Voici un code similaire au vôtre:
Cette dernière instruction NSLog va exécuter l'équivalent de ceci:
Cela va amener NSLog à rechercher un autre argument de chaîne, mais il n'y en a pas. En raison de la façon dont le langage C fonctionne, il va récupérer un pointeur de déchets aléatoire dans la pile et essayer de le traiter comme une NSString. Cela plantera très probablement votre programme. Maintenant, vos chaînes ne contiennent probablement pas de% @, mais un jour, elles le pourraient. Vous devez toujours utiliser une chaîne de format avec des données que vous contrôlez explicitement comme premier argument des fonctions qui acceptent des chaînes de format (printf, scanf, NSLog, - [NSString stringWithFormat:], ...).
Comme le souligne Otto, vous devriez probablement faire quelque chose comme:
la source
Réponse finale: comme Jon Hess l'a dit, c'est un problème de sécurité car vous passez une chaîne WHATEVER à une fonction qui attend une chaîne de format. Autrement dit, il évaluera tous les spécificateurs de format DANS la chaîne de caractères. S'il n'y en a pas, c'est génial, mais s'il y en a, de mauvaises choses pourraient arriver.
La bonne chose à faire, alors, est d'utiliser directement une chaîne de format, par exemple
De cette façon, même s'il existe des spécificateurs de format dans myNSString, ils ne sont pas évalués par NSLog.
la source
Je ne recommande pas spécialement de l'utiliser, car l'avertissement EST un vrai avertissement .. dans une utilisation dynamique du langage, il est possible de faire des choses à l'exécution sur la chaîne (c'est-à-dire insérer de nouvelles informations ou même planter le programme) .. Cependant, c'est possible pour 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"
Je dirais à GCC d'ignorer temporairement l'avertissement de compilation. Encore une fois, cela ne résout rien, mais il peut arriver que vous ne puissiez pas trouver un bon moyen de résoudre le problème.
EDIT: Depuis clang, le pragma a changé. Voir ceci: https://stackoverflow.com/a/17322337/3937
la source
Le moyen le plus rapide de résoudre ce problème serait d'ajouter
@"%@",
comme premier argument à votreNSLog
appel, c'est-à-dire,Cependant, vous devriez probablement considérer la réponse de Sixteen Otto.
la source
Je viens de passer un zéro pour annuler les avertissements, peut-être que cela fonctionnerait pour vous?
NSLog (myString, nil);
la source
myString
, le premier ira bien, mais le second ramassera les déchets de la pile. La liste de substitution dansNSLog()
n'est jamaisnil
terminée, @Vendu. Il existe deux options pour déterminer la longueur de la liste d'arguments: une valeur sentinelle, ou ce qui est utilisé dansprintf()
et family - un autre argument qui permet le calcul du nombre (par exemple, en comptant les spécificateurs de format).Si vous voulez vous débarrasser de l'avertissement "format pas un littéral de chaîne et aucun argument de format" une fois pour toutes, vous pouvez désactiver le paramètre d'avertissement GCC "Typecheck Calls to printf / scanf" (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) dans les paramètres de construction de votre cible.
la source
NSLog () attend une chaîne de format, ce qui est passé n'est qu'une chaîne. Vous n'avez pas besoin d'utiliser stringWithFormat :, vous pouvez simplement faire:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
Et cela ferait disparaître l'avertissement.
la source
FWIW, cela s'applique également aux développeurs iPhone. Je suis en train de coder avec le SDK 3.1.3 et j'ai eu la même erreur avec le même problème (nesting stringWithFormat dans NSLog ()). Sixten et Jon sont sur l'argent.
la source
Le simple fait de faire savoir à quiconque d'utiliser le
appendFormat
on NSMutableString peut également provoquer l'apparition de cet avertissement si vous essayez de transmettre une chaîne formatée comme ceci:Donc, pour éviter cet avertissement, transformez ce qui précède en ceci:
Plus concis et plus sûr. Prendre plaisir!
la source
la source
stringWithFormat
est redondante ici alors que vous pouvez simplement le faireNSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])