objective-c 警告:“格式不是字符串文字,也没有格式参数”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1677824/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Warning: "format not a string literal and no format arguments"
提问by Alexi Groove
Since upgrading to the latest Xcode 3.2.1 and Snow Leopard, I've been getting the warning
自从升级到最新的 Xcode 3.2.1 和 Snow Leopard 以来,我一直收到警告
"format not a string literal and no format arguments"
“格式不是字符串文字,也没有格式参数”
from the following code:
从以下代码:
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
NSLog([NSString stringWithFormat:@"%@ %@, %@",
errorMsgFormat,
error,
[error userInfo]]);
}
If errorMsgFormatis an NSStringwith format specifiers (eg: "print me like this: %@"), what is wrong with the above NSLogcall? And what is the recommended way to fix it so that the warning isn't generated?
如果errorMsgFormat是NSStringwith 格式说明符(例如"print me like this: %@":),上面的NSLog调用有什么问题?什么是修复它的推荐方法,以便不生成警告?
回答by Jon Hess
Xcode is complaining because this is a security problem.
Xcode 正在抱怨,因为这是一个安全问题。
Here's code similar to yours:
这是类似于您的代码:
NSString *nameFormat = @"%@ %@";
NSString *firstName = @"Jon";
NSString *lastName = @"Hess %@";
NSString *name = [NSString stringWithFormat:nameFormat, firstName, lastName];
NSLog(name);
That last NSLog statement is going to be executing the equivalent of this:
最后一个 NSLog 语句将执行与此等效的语句:
NSLog(@"Jon Hess %@");
That's going to cause NSLog to look for one more string argument, but there isn't one. Because of the way the C language works, it's going to pick up some random garbage pointer from the stack and try to treat it like an NSString. This will most likely crash your program. Now your strings probably don't have %@'s in them, but some day they might. You should always use a format string with data you explicitly control as the first argument to functions that take format strings (printf, scanf, NSLog, -[NSString stringWithFormat:], ...).
这将导致 NSLog 再寻找一个字符串参数,但没有一个。由于 C 语言的工作方式,它将从堆栈中拾取一些随机的垃圾指针并尝试将其视为 NSString。这很可能会使您的程序崩溃。现在,您的字符串中可能没有 %@,但总有一天它们可能会出现。您应该始终将格式字符串与您明确控制的数据一起用作采用格式字符串(printf、scanf、NSLog、-[NSString stringWithFormat:]、...)的函数的第一个参数。
As Otto points out, you should probably just do something like:
正如 Otto 指出的那样,您可能应该执行以下操作:
NSLog(errorMsgFormat, error, [error userInfo]);
回答by Sixten Otto
Are you nesting your brackets correctly? I don't think NSLog()likes taking only one argument, which is what you're passing it. Also, it already does the formatting for you. Why not just do this?
您是否正确嵌套了括号?我不认为NSLog()喜欢只接受一个论点,这就是你要传递的论点。此外,它已经为您进行了格式化。为什么不这样做呢?
NSLog(@"%@ %@, %@",
errorMsgFormat,
error,
[error userInfo]);
Or, since you say errorMsgFormatis a format string with a single placeholder, are you trying to do this?
或者,既然您说的errorMsgFormat是带有单个占位符的格式字符串,您是否要这样做?
NSLog(@"%@, %@", [NSString stringWithFormat:errorMsgFormat, error],
[error userInfo]);
回答by Alex Whittemore
Final answer: As Jon Hess said, it's a security issue because you're passing a WHATEVER string to a function expecting a format string. That is, it'll evaluate all format specifiers WITHIN the whatever string. If there aren't any, awesome, but if there are, bad things could happen.
最终答案:正如 Jon Hess 所说,这是一个安全问题,因为您将 WHATEVER 字符串传递给需要格式字符串的函数。也就是说,它将评估任何字符串内的所有格式说明符。如果没有,真棒,但如果有,坏事可能会发生。
The proper thing to do, then, is USE a format string directly, for example
正确的做法是直接使用格式字符串,例如
NSLog(@"%@", myNSString);
That way, even if there are format specifiers in myNSString, they don't get evaluated by NSLog.
这样,即使 myNSString 中有格式说明符,它们也不会被 NSLog 评估。
回答by Qrikko
I don't especially recommend using this, since the warning IS a real warning.. in a dynamic use of the language it's possible to do things runtime to the string (i.e. insert new information or even crash the program).. However it's possible to force suppress if you KNOW that it should be like this and you really don't want to be warned about it..
我不特别推荐使用它,因为警告是一个真正的警告..在语言的动态使用中,可以在运行时对字符串执行操作(即插入新信息甚至使程序崩溃)..但是这是可能的如果您知道它应该是这样的并且您真的不想被警告,则强制抑制它..
#pragma GCC diagnostic ignored "-Wformat-security"
#pragma GCC diagnostic ignored "-Wformat-security"
Would tell GCC to temporarily ignore the compilation warning.. Again it's not solving anything but there may be times when you can't find a good way to actually fix the problem.
会告诉 GCC 暂时忽略编译警告.. 同样,它没有解决任何问题,但有时您可能找不到实际解决问题的好方法。
EDIT: As of clang, the pragma has changed. See this: https://stackoverflow.com/a/17322337/3937
编辑:从 clang 开始,pragma 已经改变。看到这个:https: //stackoverflow.com/a/17322337/3937
回答by Martytoof
I've just been passing a nil to negate the warnings, maybe that would work for you?
我刚刚传递了一个 nil 来否定警告,也许这对你有用?
NSLog(myString, nil);
NSLog(myString, nil);
回答by Anthony Cramp
Quickest way to fix it would be to add @"%@",as the first argument to your NSLogcall, i.e.,
解决它的最快方法是将@"%@",第一个参数添加到您的NSLog调用中,即,
NSLog(@"%@", [NSString stringWithFormat: ....]);
Though, you should probably consider Sixteen Otto's answer.
不过,您可能应该考虑十六奥托的回答。
回答by aldi
If you want get rid of the warning "format not a string literal and no format arguments" once and for all, you can disable the GCC warning setting "Typecheck Calls to printf/scanf" (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) in your target's build settings.
如果您想一劳永逸地摆脱警告“格式不是字符串文字和没有格式参数”,您可以在目标的构建设置中禁用 GCC 警告设置“Typecheck Calls to printf/scanf”(GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO)。
回答by Elfred
NSLog() expects a format string, what is getting passed in is just a string. You do not need to use stringWithFormat:, you can just do:
NSLog() 需要一个格式字符串,传入的只是一个字符串。你不需要使用 stringWithFormat:,你可以这样做:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
And that would make the warning go away.
这将使警告消失。
回答by Pettiross
FWIW, this applies to iPhone dev as well. I'm coding against the 3.1.3 SDK, and got the same error with the same problem (nesting stringWithFormat inside NSLog()). Sixten and Jon are on the money.
FWIW,这也适用于 iPhone 开发。我正在针对 3.1.3 SDK 进行编码,并且遇到了同样的错误(在 NSLog() 中嵌套 stringWithFormat)。Sixten 和 Jon 很有钱。
回答by ColossalChris
Just letting anyone know using the appendFormaton NSMutableString can also cause this warning to appear if trying to pass in a formatted string like so:
只是让任何人知道appendFormat在 NSMutableString 上使用也可能导致此警告出现,如果尝试传递像这样的格式化字符串:
NSMutableString *csv = [NSMutableString stringWithString:@""];
NSString *csvAddition = [NSString stringWithFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING];
[csv appendFormat:csvAddition];
So to avoid this warning, turn the above into this:
所以为了避免这个警告,把上面的变成这样:
NSMutableString *csv = [NSMutableString stringWithString:@""];
[csv appendFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING];
More concise and more secure. Enjoy!
更简洁,更安全。享受!

