Advertencia: “formatee no un literal de cadena y ningún argumento de formato”

Desde que actualicé a la última versión de Xcode 3.2.1 y Snow Leopard, recibí la advertencia

“formato no es un literal de cadena ni argumentos de formato”

del siguiente código:

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

Si errorMsgFormat es un NSString con especificadores de formato (p. Ej .: "print me like this: %@" NSString "print me like this: %@" ), ¿qué NSLog con la llamada NSLog anterior? ¿Y cuál es la forma recomendada de solucionarlo para que no se genere la advertencia?

¿Estás anidando tus corchetes correctamente? No creo que a NSLog() le guste tomar solo un argumento, que es lo que le está pasando. Además, ya tiene el formato para ti. ¿Por qué no solo hacer esto?

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

O bien, como dices que errorMsgFormat es una cadena de formato con un único marcador de posición, ¿estás intentando hacer esto?

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

Xcode se queja porque este es un problema de seguridad.

Aquí hay un código similar al tuyo:

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

Esa última statement NSLog va a ejecutar el equivalente de esto:

 NSLog(@"Jon Hess %@"); 

Eso hará que NSLog busque otro argumento de cadena, pero no hay uno. Debido a la forma en que funciona el lenguaje C, recogerá un puntero de basura aleatorio de la stack e intentará tratarlo como un NSString. Es muy probable que esto bloquee tu progtwig. Ahora sus cadenas probablemente no tengan% @ ‘s en ellas, pero algún día podrían hacerlo. Siempre debe usar una cadena de formato con los datos que controla explícitamente como primer argumento para las funciones que toman cadenas de formato (printf, scanf, NSLog, – [NSString stringWithFormat:], …).

Como señala Otto, probablemente deberías hacer algo como:

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

Respuesta final: como dijo Jon Hess, es un problema de seguridad porque está pasando una cadena WHATEVER a una función esperando una cadena de formato. Es decir, evaluará todos los especificadores de formato DENTRO de cualquier cadena. Si no hay ninguno, increíble, pero si lo hay, pueden pasar cosas malas.

Lo correcto para hacer, entonces, es usar una cadena de formato directamente, por ejemplo

 NSLog(@"%@", myNSString); 

De esta forma, incluso si hay especificadores de formato en myNSString, NSLog no los evalúa.

No recomiendo especialmente usar esto, ya que la advertencia ES una advertencia real … en un uso dynamic del lenguaje es posible hacer cosas en tiempo de ejecución para la cadena (es decir, insertar información nueva o incluso bloquear el progtwig) .. Sin embargo, es posible forzar suprimir si SABES que debería ser así y realmente no quieres que te lo advierta.

#pragma GCC diagnostic ignored "-Wformat-security"

Le diría a GCC que ignore temporalmente la advertencia de comstackción. De nuevo, no está solucionando nada, pero puede haber ocasiones en las que no se puede encontrar una buena manera de solucionar realmente el problema.

EDITAR: A partir de clang, el pragma ha cambiado. Ver esto: https://stackoverflow.com/a/17322337/3937

La forma más rápida de solucionarlo sería agregar @"%@", como primer argumento de su llamada NSLog , es decir,

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

Sin embargo, probablemente deberías considerar la respuesta de Sixteen Otto.

He estado pasando un cero por negar las advertencias, ¿quizás eso funcionaría para ti?

NSLog (myString, nil);

NSLog () espera una cadena de formato, lo que se transfiere es solo una cadena. No necesita usar stringWithFormat :, puede hacer lo siguiente:

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

Y eso haría que la advertencia desaparezca.

Si desea deshacerse del formato de advertencia “no literal de cadena ni de formato” de una vez por todas, puede desactivar la configuración de advertencia de GCC “Llamar a Llamar Llamar a printf / scanf” (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) en la configuración de creación de su objective.

FWIW, esto también se aplica al iPhone dev. Estoy codificando contra el SDK 3.1.3, y obtuve el mismo error con el mismo problema (nesting stringWithFormat dentro de NSLog ()). Sixten y Jon están en el dinero.

El hecho de que alguien sepa utilizando el appendFormat en NSMutableString también puede hacer que aparezca esta advertencia si intenta pasar una cadena formateada de la siguiente manera:

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

Para evitar esta advertencia, convierta lo anterior en esto:

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

Más conciso y más seguro. ¡Disfrutar!

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