格式字符串中的免费'%'非常令人惊讶。
#include <iostream>
#include <stdarg.h>
#include <stdio.h>
void foo(const char *format, ...) {
const size_t buffSize = 1024;
char msg[buffSize];
{
va_list args;
va_start(args, format);
_vsnprintf(msg, buffSize, format, args);
va_end(args);
std::cout << msg << std::endl; // here you get a,b,,c,d,e
}
{
va_list args;
va_start(args, format);
_vsnprintf_s(msg, buffSize, format, args); // and here you crash and burn
va_end(args);
std::cout << msg << std::endl;
}
}
int _tmain(int argc, _TCHAR *argv[]) {
foo("%s,b,%,c,d,%s", "a", "e");
return 0;
}
这不是您期望获得的,尤其是在以下is stated by Microsoft
时如果百分号后跟一个没有意义的字符 格式字段,字符被复制到输出不变。
那么我们在这里看到了什么?一个bug?从何时起?它是固定的msvc12 / 13?
EDIT01: 好吧,我误读了这个陈述,让我们专注于崩溃
#include <iostream>
#include <stdarg.h>
#include <stdio.h>
void foo(const char *format, ...) {
const size_t buffSize = 1024;
char msg[buffSize];
va_list args;
va_start(args, format);
_vsnprintf_s(msg, buffSize, format, args);
va_end(args);
std::cout << msg << std::endl;
}
int main(int argc, char *argv[]) {
foo("b,%,c,d"); // crash here
foo("%s,b,%,c,d,%s", "a", "e"); // there and everywhere
return 0;
}
EDIT02:
得到了Microsoft Connect的回答
感谢您就此问题与Microsoft联系。我们发现了我们 遗漏了有关安全功能如何表现的重要信息 从格式规范语法页面。安全功能 格式字符串的附加验证,并调用无效 参数处理程序,如果意外字符跟在初始%之后 字符。默认情况下,这将使用Dr. Watson终止程序 报告。在调试模式下,它首先导致断言。更多信息是 可在参数验证主题中找到 https://msdn.microsoft.com/en-us/library/ksazx244.aspx。格式 正在使用此信息更新“规范语法”页面。 期待在下周看到Visual Studio 2013的更新页面 左右。
答案 0 :(得分:2)
这实际上是一个文档错误。在Format Specification Syntax主题中应尽快出现更正(给它一两天)。缺少的信息是格式化函数的安全版本(具有尾随 _s 的安全版本)对格式化字符串执行额外验证,并且它们拒绝百分比字符,后跟意外字符。然后,在这种情况下,它们会调用无效参数处理程序,而非安全版本则不会。默认情况下,这将终止程序并调用Dr. Watson报告机制。
如果您正在尝试处理任意格式字符串问题,可以通过调用_set_invalid_parameter_handler来自行设置无效参数处理程序以捕获此类情况,并防止崩溃。在DEBUG构建中,此格式字符串应导致无效的参数断言。 Parameter Validation下的Security Features in the CRT主题提供了更多信息。