警告:“格式不是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]);