翻译《有关编程、重构及其他的终极问题?》——20.光对文件做EOF检查可能还不够

翻译《有关编程、重构及其他的终极问题?》——20.光对文件做EOF检查可能还不够

标签(空格分隔): 翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2017年02月24日


20.光对文件做EOF检查可能还不够

下面的代码来自SETI@home项目。PVS-Studio诊断的错误说明为:V663 Infinite loop is possible. The ‘cin.eof()’ condition is insufficient to break from the loop. Consider adding the ‘cin.fail()’ function call to the conditional expression(译者注:大意是说这个循环可能是无限的,因为’cin.eof()‘还不足够终止循环,还要考虑增加对’cin.fail()‘函数调用的判断)。

template <typename T>
std::istream &operator >>(std::istream &i, sqlblob<T> &b) 
{
  ....
  while (!i.eof()) 
  {
    i >> tmp;
    buf+=(tmp+' ');
  }
  ....
}

解释
从对象流中读取数据的操作并非看上去那么繁琐。当程序员从流中读取数据时通常调用eof()方法检查是否到达流的结尾。然后,这种检查方式其实并不合适,因为检查的不完整,当读取流的过程中有错误发生时就不能被发现,就会导致循环不会结束。

注意:这里提到的问题同时适用于输入和输出流,但为了避免重复,我们这里只讨论一种情况。

这就是上面代码中程序员犯的错误:当在读取数据过程中一旦发生错误,就会因为eof()方法始终返回false而导致循环不会终止。除此之外,不正确的数据就会在循环中被处理,因为未知的值会被赋予tmp变量中。

为了避免这种情况,我们需要使用额外的方法去检查流的状态,比如bad(),fail()等函数。

正确的代码
让我们利用一下流可以隐含转换为bool类型的事实。ture就意味着值被成功的读取。关于这点更多的细节可以在StackOverflow上找到

template <typename T>
std::istream &operator >>(std::istream &i, sqlblob<T> &b) 
{
  ....
  while (i >> tmp) 
  {
    buf+=(tmp+' ');
  }
  ....
}

建议
当从流中读取数据时,不要只使用eof()方法,应该检查任何可能的失败。

使用如bad()或fail()等方法检查流的状态。前者用于检查流的内部错误,后者用于检查读取数据的错误。

然后,使用bool()操作符更方便,正如前例所示。

猜你喜欢

转载自blog.csdn.net/headman/article/details/56846708