Desde que actualicé a la última versión de Xcode 3.2.1 y Snow Leopard, he recibido la advertencia
"formato no es una cadena literal 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
formato con especificadores (por ejemplo:) "print me like this: %@"
, ¿qué hay de malo en la NSLog
llamada anterior ? ¿Y cuál es la forma recomendada de solucionarlo para que no se genere la advertencia?
objective-c
warnings
string-formatting
nslog
Alexi Groove
fuente
fuente
NSLog()
puede tomar un argumento, cuando la cadena de formato no contiene especificadores de formato.Xcode se queja porque se trata de un problema de seguridad.
Aquí hay un código similar al tuyo:
Esa última declaración NSLog ejecutará el equivalente a esto:
Eso hará que NSLog busque un argumento de cadena más, pero no hay uno. Debido a la forma en que funciona el lenguaje C, tomará un puntero de basura aleatorio de la pila e intentará tratarlo como un NSString. Lo más probable es que esto bloquee su programa. Ahora tus cadenas probablemente no tengan% @ en ellas, pero algún día podrían tenerlas. Siempre debe usar una cadena de formato con datos que controle 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:
fuente
Respuesta final: como dijo Jon Hess, es un problema de seguridad porque está pasando una cadena CUALQUIER a una función que espera una cadena de formato. Es decir, evaluará todos los especificadores de formato DENTRO de la cadena. Si no los hay, genial, pero si los hay, pueden pasar cosas malas.
Entonces, lo correcto es USAR una cadena de formato directamente, por ejemplo
De esa manera, incluso si hay especificadores de formato en myNSString, NSLog no los evalúa.
fuente
No recomiendo especialmente usar esto, ya que la advertencia ES una advertencia real ... en un uso dinámico del lenguaje es posible hacer cosas en tiempo de ejecución de la cadena (es decir, insertar nueva información o incluso bloquear el programa). Sin embargo, es posible forzar la supresión si SABES que debería ser así y realmente no quieres que te adviertan sobre ello.
#pragma GCC diagnostic ignored "-Wformat-security"
Le diría a GCC que ignore temporalmente la advertencia de compilación. Una vez más, no resuelve nada, pero puede haber ocasiones en las que no pueda encontrar una buena manera de solucionar el problema.
EDITAR: A partir de clang, el pragma ha cambiado. Vea esto: https://stackoverflow.com/a/17322337/3937
fuente
La forma más rápida de solucionarlo sería agregar
@"%@",
como primer argumento a suNSLog
llamada, es decir,Sin embargo, probablemente deberías considerar la respuesta de Sixteen Otto.
fuente
Acabo de pasar un cero para negar las advertencias, ¿tal vez eso funcione para usted?
NSLog (myString, nulo);
fuente
myString
, el primero estará bien, pero el segundo recogerá la basura de la pila. La lista de sustitución enNSLog()
está nonil
terminada en, @Sold. Hay dos opciones para averiguar qué tan larga es la lista de argumentos: un valor centinela, o lo que se usa enprintf()
y familia, otro argumento que permite calcular el número (por ejemplo, contando los especificadores de formato).Si desea deshacerse de la advertencia "formato, no una cadena literal y sin argumentos de formato" de una vez por todas, puede desactivar la configuración de advertencia de GCC "Typecheck Calls to printf / scanf" (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) en la configuración de compilación de su objetivo.
fuente
NSLog () espera una cadena de formato, lo que se pasa es solo una cadena. No es necesario utilizar stringWithFormat :, solo puede hacer:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
Y eso haría que la advertencia desapareciera.
fuente
FWIW, esto también se aplica a los desarrolladores de iPhone. Estoy codificando contra el SDK 3.1.3 y obtuve el mismo error con el mismo problema (anidando stringWithFormat dentro de NSLog ()). Sixten y Jon están en el dinero.
fuente
El solo hecho
appendFormat
de informar a cualquiera que use on NSMutableString también puede hacer que aparezca esta advertencia si intenta pasar una cadena formateada como esta:Entonces, para evitar esta advertencia, convierta lo anterior en esto:
Más conciso y seguro. ¡Disfrutar!
fuente
fuente
stringWithFormat
es redundante aquí cuando podría hacerloNSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])