当前位置:  开发笔记 > 编程语言 > 正文

警告:"格式不是字符串文字,没有格式参数"

如何解决《警告:"格式不是字符串文字,没有格式参数"》经验,为你挑选了6个好方法。

自升级到最新的Xcode 3.2.1和Snow Leopard以来,我一直在收到警告

"格式不是字符串文字,没有格式参数"

来自以下代码:

NSError *error = nil;

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

}

如果errorMsgFormatNSString格式说明符(例如"print me like this: %@":),上面的NSLog调用有什么问题?什么是修复它的建议方法,以便不生成警告?



1> Jon Hess..:

Xcode抱怨,因为这是一个安全问题.

这里的代码类似于你的代码:

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

最后一个NSLog语句将执行相当于这个:

NSLog(@"Jon Hess %@");

这将导致NSLog再查找一个字符串参数,但没有一个.由于C语言的工作方式,它将从堆栈中获取一些随机垃圾指针并尝试将其视为NSString.这很可能会导致程序崩溃.现在你的字符串可能没有%@,但有一天他们可能会.您应该始终使用格式字符串和您明确控制的数据作为采用格式字符串的函数的第一个参数(printf,scanf,NSLog, - [NSString stringWithFormat:],...).

正如奥托指出的那样,你应该做的事情就像:

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


再一次在SO上,详细而好的答案落到了路边.感谢您完全解释这一点.我永远都不会想到这一点.

2> Sixten Otto..:

你正确地嵌套括号吗?我不认为NSLog()喜欢只拿一个论点,这就是你传递的.此外,它已经为您进行格式化.为什么不这样做呢?

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

或者,既然你说errorMsgFormat是一个带有单个占位符的格式字符串,你试图这样做吗?

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


"我不认为NSLog()喜欢只接受一个参数"`NSLog()`可以接受一个参数,格式字符串不包含格式说明符.

3> Alex Whittem..:

最后的答案:正如Jon Hess所说,这是一个安全问题,因为你将WHATEVER字符串传递给期望格式字符串的函数.也就是说,它将在所有字符串中评估所有格式说明符.如果没有,真棒,但如果有,可能会发生坏事.

那么,正确的做法就是直接使用格式字符串

NSLog(@"%@", myNSString);

这样,即使myNSString中有格式说明符,它们也不会被NSLog评估.



4> 小智..:

我不特别推荐使用它,因为警告是一个真正的警告..在动态使用该语言时,可以对字符串执行运行时(即插入新信息甚至使程序崩溃)..但是它可能如果你知道它应该像这样强制抑制你真的不想被警告它...

#pragma GCC diagnostic ignored "-Wformat-security"

会告诉GCC暂时忽略编译警告..再次它没有解决任何问题,但有时候你找不到一个好方法来解决问题.

编辑:从铿锵来看,这个实用主义已经改变了.请参阅:https://stackoverflow.com/a/17322337/3937



5> Anthony Cram..:

解决它的最快方法是添加@"%@",作为NSLog调用的第一个参数,即

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

虽然,你应该考虑十六奥托的回答.



6> Martytoof..:

我刚刚通过一个零否定警告,也许这对你有用吗?

NSLog(myString,nil);


有人可以解释为什么传递零作为第二个参数解决警告?
这可能会停止编译器警告,但是[Jon Hess解释](http://stackoverflow.com/a/1678313/)的基础问题仍然存在 - 如果`myString中有多个格式说明符,第一个会很好,但第二个将从堆栈中拾取垃圾.`NSLog()`中的替换列表是_never_`nil`-terminated,@ Sale.有两个选项可以确定参数列表的长度:一个sentinel值,或者`printf()`和family中使用的值 - 另一个允许计算数字的参数(例如,通过计算格式说明符).
推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有