警告:“格式不是string文字和格式参数”
自升级到最新的Xcode 3.2.1和Snow Leopard以来,我一直在收到警告
“格式不是string文字和格式参数”
从下面的代码:
NSError *error = nil; if (![self.managedObjectContext save:&error]) { NSLog([NSString stringWithFormat:@"%@ %@, %@", errorMsgFormat, error, [error userInfo]]); }
如果errorMsgFormat
是带格式说明符的NSString
(例如: "print me like this: %@"
),上面的NSLog
调用有什么问题? 什么是build议的方式来解决它,使警告不会产生?
你正确地嵌套你的括号吗? 我不认为NSLog()
喜欢只有一个参数,这是你通过它。 此外,它已经为你的格式。 为什么不这样做呢?
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo]);
或者,既然你说errorMsgFormat
是一个占位符的格式化string,你是否试图做到这一点?
NSLog(@"%@, %@", [NSString stringWithFormat:errorMsgFormat, error], [error userInfo]);
Xcode抱怨,因为这是一个安全问题。
这是类似于你的代码:
NSString *nameFormat = @"%@ %@"; NSString *firstName = @"Jon"; NSString *lastName = @"Hess %@"; NSString *name = [NSString stringWithFormat:nameFormat, firstName, lastName]; NSLog(name);
最后一个NSLog语句将执行相当于这个:
NSLog(@"Jon Hess %@");
这将导致NSLog寻找一个更多的string参数,但没有一个。 由于C语言的工作原理,它会从堆栈中拾取一些随机的垃圾指针,并尝试像NSString一样对待它。 这很可能会导致程序崩溃。 现在你的string可能没有%@,但有一天他们可能会。 你应该总是使用格式化string和你明确控制的数据作为格式化string的函数的第一个参数(printf,scanf,NSLog, – [NSString stringWithFormat:],…)。
正如奥托所指出的那样,你应该做一些如下的事情:
NSLog(errorMsgFormat, error, [error userInfo]);
最终答案:正如Jon Hess所说,这是一个安全问题,因为您正在将WHATEVERstring传递给需要格式string的函数。 也就是说,它将评估所有格式说明符WITHIN的任何string。 如果没有,真棒,但如果有的话,可能会发生不好的事情。
例如,正确的做法是直接使用格式string
NSLog(@"%@", myNSString);
这样,即使在myNSString中有格式说明符,也不会被NSLog评估。
我不特别推荐使用这个,因为警告是一个真正的警告..在dynamic使用的语言,它可能做的事情运行时的string(即插入新的信息,甚至崩溃的程序)..然而,这是可能的强行压制,如果你知道它应该是这样的,你真的不想被警告它..
#pragma GCC diagnostic ignored "-Wformat-security"
会告诉GCC暂时忽略编译警告。再次,它不是解决任何问题,但有时你可能找不到一个好方法来解决问题。
编辑:至于clang,杂注已经改变。 看到这个: https : //stackoverflow.com/a/17322337/3937
最快的方法来解决它将添加@"%@",
作为您的NSLog
调用的第一个参数,即,
NSLog(@"%@", [NSString stringWithFormat: ....]);
虽然,你应该考虑十六奥托的答案。
我刚刚通过否定警告,也许这会为你工作?
NSLog(myString,nil);
NSLog()期望一个格式string,传入的只是一个string。 你不需要使用stringWithFormat:,你可以这样做:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
这会使警告消失。
如果您希望一劳永逸地摆脱“格式化不是string文本和格式参数”的警告,可以在目标的构build设置中禁用GCC警告设置“Typecheck调用printf / scanf”(GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO)。
FWIW,这也适用于iPhone开发。 我编码对3.1.3 SDK,并得到了同样的问题(在NSLog()内嵌套stringWithFormat)相同的错误)。 Sixten和Jon在钱上。
让任何人都知道在NSMutableString上使用appendFormat
也会导致这个警告出现,如果试图传递一个格式化的string,如下所示:
NSMutableString *csv = [NSMutableString stringWithString:@""]; NSString *csvAddition = [NSString stringWithFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING]; [csv appendFormat:csvAddition];
所以为了避免这个警告,把上面的代码变成这样:
NSMutableString *csv = [NSMutableString stringWithString:@""]; [csv appendFormat:@"%@",WHATEVERYOUAREPUTTINGINYOURSTRING];
更简洁,更安全。 请享用!
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo]);