转换成功与_stscanf_s C库函数,但实际上失败

时间:2016-07-09 16:49:34

标签: c visual-studio

这个问题附带内置答案,但无论如何,我想分享这个小小的战争故事,看看它有可能帮助别人......

如果输入" 20160708",您是否看到以下C语句出了什么问题?这些摘自某些代码,用于检查是否存在软件更新可用...

struct tm ParseTime;
memset(&ParseTime, 0, sizeof(ParseTime));

// Extract date information
int ScanResult = _stscanf_s(UTCDate, _T("%4i%2i%2i"), 
  &ParseTime.tm_year, &ParseTime.tm_mon, &ParseTime.tm_mday);

if (ScanResult != 3)
  DEBUG_MESSAGE(MB_OK | MB_ICONERROR, _T("Debug:  Unexpected Error"),
    _T("ConvertUTCDateTime - could not scan UTCDate = '%s', ScanResult = %d"), 
    UTCDate, ScanResult);

起初我们没有。以上代码多次通过系统测试。

但是在7月8日,它在后来的assert语句中引发了异常而没有发出DEBUG_MESSAGE。

调试显示,即使ScanResult加载了预期值3,意味着成功转换了3个字段,ParseTime.tm_mday字段实际上加载了0,这是一个无效的月份数字!

但是'我'格式说明符表示"整数",对吗?那么问题是什么?

1 个答案:

答案 0 :(得分:0)

我们突然想到了......

来自C库文档(https://msdn.microsoft.com/en-us/library/6ttkkkhh.aspx

i - An integer.

Hexadecimal if the input string begins with "0x" or "0X",
octal if the string begins with "0", otherwise decimal.

好的,"一个整数"。没关系,对吗?

<强>可是...

阅读整个说明...... OCTAL?!?我们这里有一个回溯到20世纪70年代!

没错,&#39; 0&#39;字符都导致转换转换为八进制,并继续转换为零。然后转换将停止在无效(对于八进制)&#39; 8&#39;或者&#39; 9&#39;字符,意思是上述代码仅在本月8日和9日或者在第8个月或第9个月以最坏的方式失败!

是否使用&#34;%2i&#34;扫描是否有争议?格式规范应考虑转换&#34; 08&#34;或&#34; 09&#34;那么,实际上它确实是成功的 - 无论如何都是当前的Microsoft CRT库。

当然,修复是使用&#34;%4u%2u%2u&#34;对于格式说明符,它明确选择十进制转换。

故事的道德......始终一直读到段落的末尾。

要么在本月的8日或9日,也要在8月或9月发布新软件。 : - )