Desde a atualização para o Xcode 3.2.1 e Snow Leopard mais recente, tenho recebido o aviso
"formato não é uma string literal e sem argumentos de formato"
do seguinte código:
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
NSLog([NSString stringWithFormat:@"%@ %@, %@",
errorMsgFormat,
error,
[error userInfo]]);
}
Se errorMsgFormat
for um NSString
com especificadores de formato (por exemplo "print me like this: %@"
:), o que há de errado com a NSLog
chamada acima ? E qual é a forma recomendada de corrigir isso para que o aviso não seja gerado?
objective-c
warnings
string-formatting
nslog
Alexi Groove
fonte
fonte
NSLog()
pode aceitar um argumento, quando a string de formato não contém especificadores de formato.O Xcode está reclamando porque isso é um problema de segurança.
Este é um código semelhante ao seu:
Essa última instrução NSLog executará o equivalente a isto:
Isso fará com que o NSLog procure mais um argumento de string, mas não há nenhum. Por causa da maneira como a linguagem C funciona, ela pegará algum ponteiro de lixo aleatório da pilha e tentará tratá-lo como um NSString. Isso provavelmente irá travar seu programa. Agora, suas strings provavelmente não têm% @'s nelas, mas algum dia poderão. Você deve sempre usar uma string de formato com dados que você controla explicitamente como o primeiro argumento para funções que usam strings de formato (printf, scanf, NSLog, - [NSString stringWithFormat:], ...).
Como Otto aponta, você provavelmente deve apenas fazer algo como:
fonte
Resposta final: Como Jon Hess disse, é um problema de segurança porque você está passando uma string DE QUALQUER COISA para uma função que espera uma string de formato. Ou seja, ele avaliará todos os especificadores de formato DENTRO de qualquer string. Se não houver nenhum, ótimo, mas se houver, coisas ruins podem acontecer.
A coisa certa a fazer, então, é USE uma string de formato diretamente, por exemplo
Dessa forma, mesmo se houver especificadores de formato em myNSString, eles não serão avaliados pelo NSLog.
fonte
Eu não recomendo especialmente usar isso, já que o aviso É um aviso real .. em um uso dinâmico da linguagem é possível fazer coisas em tempo de execução para a string (ou seja, inserir novas informações ou mesmo travar o programa). No entanto, é possível forçar a supressão se você SABE que deveria ser assim e você realmente não quer ser avisado sobre isso ..
#pragma GCC diagnostic ignored "-Wformat-security"
Diria ao GCC para ignorar temporariamente o aviso de compilação. Novamente, não está resolvendo nada, mas pode haver momentos em que você não consegue encontrar uma boa maneira de realmente consertar o problema.
EDIT: A partir do clang, o pragma mudou. Veja isto: https://stackoverflow.com/a/17322337/3937
fonte
A maneira mais rápida de corrigir isso seria adicionar
@"%@",
o primeiro argumento à suaNSLog
chamada, ou seja,Porém, você provavelmente deveria considerar a resposta de Dezesseis Otto.
fonte
Acabei de passar um zero para negar os avisos, talvez isso funcione para você?
NSLog (minhaString, nulo);
fonte
myString
, o primeiro ficará bem, mas o segundo pegará o lixo da pilha. A lista de substituição em nuncaNSLog()
é terminada, @Sold. Existem duas opções para descobrir o tamanho da lista de argumentos: um valor sentinela ou o que é usado em uma família - outro argumento que permite o cálculo do número (por exemplo, contando os especificadores de formato).nil
printf()
Se você quiser se livrar do aviso "formato não é uma string literal e sem argumentos de formato" de uma vez por todas, você pode desativar a configuração de aviso do GCC "Typecheck Calls to printf / scanf" (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) nas configurações de compilação do seu destino.
fonte
NSLog () espera uma string de formato, o que está sendo passado é apenas uma string. Você não precisa usar stringWithFormat :, você pode apenas fazer:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
E isso faria o aviso desaparecer.
fonte
FWIW, isso se aplica ao iPhone dev também. Estou codificando com o SDK 3.1.3 e obtive o mesmo erro com o mesmo problema (aninhando stringWithFormat dentro de NSLog ()). Sixten e Jon estão no dinheiro.
fonte
Apenas avisar a alguém usando
appendFormat
NSMutableString também pode fazer com que este aviso apareça se tentar passar uma string formatada como esta:Portanto, para evitar esse aviso, transforme o acima em:
Mais conciso e mais seguro. Aproveitar!
fonte
fonte
stringWithFormat
é redundante aqui quando você poderia apenas fazerNSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])