wake-up-neo.com

Warnung: "Formatieren Sie kein String-Literal und keine Formatargumente"

Seit dem Upgrade auf den neuesten Xcode 3.2.1 und Snow Leopard erhalte ich die Warnung

"format kein String-Literal und keine Formatargumente"

aus dem folgenden Code:

NSError *error = nil;

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

}

Wenn errorMsgFormat ein NSString mit Formatangaben ist (zB: "print me like this: %@"), was ist los mit dem obigen NSLog Aufruf? Und wie kann es behoben werden, damit die Warnung nicht generiert wird?

109
Alexi Groove

Schachteln Sie Ihre Klammern richtig? Ich glaube nicht, dass es NSLog() gefällt, nur ein Argument zu verwenden, das Sie übergeben. Außerdem übernimmt es bereits die Formatierung für Sie. Warum nicht einfach so?

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

Oder, da Sie sagen, dass errorMsgFormat eine Formatzeichenfolge mit einem einzelnen Platzhalter ist, versuchen Sie dies zu tun?

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

Xcode beschwert sich, weil dies ein Sicherheitsproblem ist.

Hier ist ein Code, der Ihrem ähnlich ist:

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

Diese letzte NSLog-Anweisung wird das Äquivalent dazu ausführen:

NSLog(@"Jon Hess %@");

Das wird dazu führen, dass NSLog nach einem weiteren String-Argument sucht, aber es gibt keines. Aufgrund der Funktionsweise der C-Sprache wird ein zufälliger Speicherbereinigungszeiger vom Stapel genommen und versucht, ihn wie einen NSString zu behandeln. Dies wird höchstwahrscheinlich Ihr Programm zum Absturz bringen. Jetzt haben Ihre Saiten wahrscheinlich keine% @, aber eines Tages könnten sie. Sie sollten immer eine Formatzeichenfolge mit Daten verwenden, die Sie explizit als erstes Argument für Funktionen verwenden, die Formatzeichenfolgen verwenden (printf, scanf, NSLog, - [NSString stringWithFormat:], ...).

Wie Otto betont, sollten Sie wahrscheinlich nur Folgendes tun:

NSLog(errorMsgFormat, error, [error userInfo]);
157
Jon Hess

Letzte Antwort: Wie Jon Hess sagte, handelt es sich um ein Sicherheitsproblem, da Sie eine WHATEVER-Zeichenfolge an eine Funktion übergeben, die eine Formatzeichenfolge erwartet. Das heißt, es werden alle Formatbezeichner INNERHALB der jeweiligen Zeichenfolge ausgewertet. Wenn es keine gibt, großartig, aber wenn es solche gibt, können schlimme Dinge passieren.

Das Richtige ist dann, zum Beispiel eine Formatzeichenfolge direkt zu VERWENDEN

NSLog(@"%@", myNSString);

Auf diese Weise werden Formatbezeichner in myNSString nicht von NSLog ausgewertet.

38
Alex Whittemore

Ich empfehle dies nicht besonders, da die Warnung IS eine echte Warnung ist. Bei einer dynamischen Verwendung der Sprache ist es möglich, Dinge zur Laufzeit mit der Zeichenfolge zu tun (dh neue Informationen einzufügen oder sogar stürzt das Programm ab). Es ist jedoch möglich, die Unterdrückung zu erzwingen, wenn Sie WISSEN, dass dies so sein sollte und Sie wirklich nicht gewarnt werden möchten.

#pragma GCC diagnostic ignored "-Wformat-security"

Würde GCC anweisen, die Kompilierungswarnung vorübergehend zu ignorieren. Auch hier wird nichts behoben, aber es kann vorkommen, dass Sie keinen guten Weg finden, um das Problem tatsächlich zu beheben.

EDIT: Mit der Zeit hat sich das Pragma geändert. Siehe hierzu: https://stackoverflow.com/a/17322337/3937

13
Qrikko

Ich habe gerade eine Null überschritten, um die Warnungen zu negieren, vielleicht würde das für Sie funktionieren?

NSLog (myString, nil);

10
Martytoof

Der schnellste Weg, dies zu beheben, ist das Hinzufügen von @"%@", als erstes Argument für Ihren NSLog -Aufruf, d. h.

NSLog(@"%@", [NSString stringWithFormat: ....]);

Sie sollten jedoch wahrscheinlich die Antwort von Sixteen Otto in Betracht ziehen.

10
Anthony Cramp

Wenn Sie die Warnung "Formatiere kein Stringliteral und keine Formatargumente" ein für allemal loswerden möchten, können Sie die GCC-Warnungseinstellung "Typecheck Calls to printf/scanf" (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) in den Build-Einstellungen Ihres Ziels deaktivieren.

3
aldi

FWIW, das gilt auch für iPhone-Entwickler. Ich programmiere gegen das 3.1.3 SDK und habe den gleichen Fehler mit dem gleichen Problem erhalten (Verschachtelung von stringWithFormat in NSLog ()). Sixten und Jon sind auf dem Geld.

2
Pettiross

NSLog () erwartet eine Formatzeichenfolge, was übergeben wird, ist nur eine Zeichenfolge. Sie müssen nicht stringWithFormat: verwenden. Sie können einfach Folgendes tun:

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

Und das würde die Warnung verschwinden lassen.

2
Elfred

Wenn Sie nur wissen lassen, dass Sie appendFormat für NSMutableString verwenden, kann diese Warnung auch angezeigt werden, wenn Sie versuchen, eine formatierte Zeichenfolge wie die folgende zu übergeben:

NSMutableString *csv = [NSMutableString stringWithString:@""];
NSString *csvAddition = [NSString stringWithFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING];
[csv appendFormat:csvAddition];

Um diese Warnung zu vermeiden, gehen Sie folgendermaßen vor:

NSMutableString *csv = [NSMutableString stringWithString:@""];
[csv appendFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING];

Präziser und sicherer. Genießen!

0
ColossalChris