После обновления до последней версии Xcode 3.2.1 и Snow Leopard я получаю предупреждение
"форматировать не строковый литерал и не аргументы формата"
из следующего кода:
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
NSLog([NSString stringWithFormat:@"%@ %@, %@",
errorMsgFormat,
error,
[error userInfo]]);
}
Если errorMsgFormat
это NSString
спецификаторы формата with (например:) "print me like this: %@"
, что не так с приведенным выше NSLog
вызовом? И как это рекомендуется исправить, чтобы предупреждение не генерировалось?
objective-c
warnings
string-formatting
nslog
Алекси Грув
источник
источник
NSLog()
может принимать один аргумент, когда строка формата не содержит спецификаторов формата.Xcode жалуется, потому что это проблема безопасности.
Вот код, похожий на ваш:
Последний оператор NSLog будет выполнять эквивалент этого:
Это заставит NSLog искать еще один строковый аргумент, но его нет. Из-за того, как работает язык C, он собирает случайный указатель мусора из стека и пытается рассматривать его как NSString. Скорее всего, это приведет к сбою вашей программы. Теперь в ваших строках, вероятно, нет% @, но когда-нибудь они могут быть. Вы всегда должны использовать строку формата с данными, которыми вы явно управляете, в качестве первого аргумента для функций, которые принимают строки формата (printf, scanf, NSLog, - [NSString stringWithFormat:], ...).
Как указывает Отто, вам, вероятно, следует просто сделать что-то вроде:
источник
Окончательный ответ: как сказал Джон Хесс, это проблема безопасности, потому что вы передаете строку WHATEVER функции, ожидающей строку формата. То есть он будет оценивать все спецификаторы формата ВНУТРИ строки any. Если их нет - круто, но если есть, могут случиться плохие вещи.
В таком случае правильным будет ИСПОЛЬЗОВАТЬ строку формата напрямую, например
Таким образом, даже если в myNSString есть спецификаторы формата, они не будут оцениваться NSLog.
источник
Я особенно не рекомендую использовать это, поскольку предупреждение ЯВЛЯЕТСЯ настоящим предупреждением .. при динамическом использовании языка можно выполнять действия со строкой (т.е. вставлять новую информацию или даже сбой программы). Однако это возможно принудительно подавить, если вы ЗНАЕТЕ, что это должно быть так, и вы действительно не хотите, чтобы вас об этом предупреждали ..
#pragma GCC diagnostic ignored "-Wformat-security"
Сказал бы GCC временно игнорировать предупреждение о компиляции. Опять же, это ничего не решает, но могут быть моменты, когда вы не можете найти хороший способ решить проблему.
РЕДАКТИРОВАТЬ: Начиная с clang, прагма изменилась. Смотрите это: https://stackoverflow.com/a/17322337/3937
источник
Самый быстрый способ исправить это - добавить
@"%@",
в качестве первого аргумента вашегоNSLog
вызова, т. Е.Хотя вам, вероятно, стоит подумать об ответе Шестнадцати Отто.
источник
Я только что пропустил ноль, чтобы опровергнуть предупреждения, может быть, это сработает для вас?
NSLog (myString, ноль);
источник
myString
, с первым будет все в порядке, но второй будет собирать мусор из стека. Список подменыNSLog()
не никогдаnil
-завершённый, @Sold. Есть два варианта определения длины списка аргументов: контрольное значение или то, что используется вprintf()
и семейство - еще один аргумент, который позволяет вычислить число (например, путем подсчета спецификаторов формата).Если вы хотите избавиться от предупреждения «формат, а не строковый литерал и без аргументов формата» раз и навсегда, вы можете отключить параметр предупреждения GCC «Typecheck Calls to printf / scanf» (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) в настройках вашей целевой сборки.
источник
NSLog () ожидает строку формата, а передается просто строка. Вам не нужно использовать stringWithFormat :, вы можете просто:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
И тогда предупреждение исчезнет.
источник
FWIW, это относится и к разработчикам iPhone. Я кодирую SDK 3.1.3 и получил ту же ошибку с той же проблемой (вложение stringWithFormat внутри NSLog ()). Сикстен и Джон в деньгах.
источник
Если просто
appendFormat
сообщить кому-либо об использовании в NSMutableString, это может также вызвать появление этого предупреждения при попытке передать отформатированную строку следующим образом:Чтобы избежать этого предупреждения, превратите приведенное выше в следующее:
Более кратко и надежно. Наслаждайтесь!
источник
источник
stringWithFormat
здесь излишне, когда вы могли бы просто сделатьNSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])