【问题标题】:Why does integer overflow cause errors with C++ iostreams?为什么整数溢出会导致 C++ iostream 出错?
【发布时间】:2010-08-27 08:36:15
【问题描述】:

好的,所以我对 C++ iostreams 有一些问题,感觉很奇怪,但考虑到 MSVC++ 和 G++ 都会发生这种情况,这可能是已定义的行为。

假设我有这个程序:

#include <iostream>
using namespace std;

int main()
{
   int a;
   cin >> a;
   cout << a << endl;
   cin >> a;
   cout << a << endl;

   return 0;
}

如果我通过给第一个 cin 一个大于 int 的最大限制的值来故意溢出,则所有对 cin.operator&gt;&gt;() 的进一步调用将由于某种原因立即返回,并且 a 被设置为某个值。该值似乎未定义。

为什么,这种行为记录在哪里?有没有办法判断是否发生了这种溢出?

此外,这个类似的程序似乎可以按我的意愿工作。如果我溢出该值,它会给a 一些值,并继续,就好像溢出从未发生过一样。

#include <cstdio>
using namespace std;

int main()
{
   int a;
   scanf("%d", &a);
   printf("%d\n", a);
   scanf("%d", &a);
   printf("%d\n", a);
   scanf("%d", &a);
   printf("%d\n", a);

   return 0;
}

【问题讨论】:

    标签: c++ integer-overflow


    【解决方案1】:

    iostreams 旨在检测错误并进入错误状态。整数溢出的结果与输入非数字字符串的结果相同。

    cin(或任何流)转换为bool或检查cin.rdstate()以确定是否发生错误。

    调用cin.clear()cin.ignore() 清除错误。它将在失败的角色处拾取。

    至于官方文档,不幸的是,标准在 iostreams 的内部有点难以理解。请参阅 §27.6.1.2.1、27.6.1.2.2 和 22.2.2.1.1/11(不开玩笑):

    ——阶段 2 中累积的字符序列会导致 scanf 报告输入失败。 ios_base::failbit 分配给 err。

    documentation for scanf 同样难以理解,我相信溢出应该是一个错误。

    【讨论】:

    • 嗯,scanf 中的整数溢出实际上会导致 UB,而不是失败报告。
    【解决方案2】:

    我认为 cin 由于读取无效而将自身设置为错误状态。

    这里的第一个回复解释了它。

    http://www.dreamincode.net/forums/topic/93200-cin-checking-and-resetting-error-state/

    刚刚试过这段代码,它似乎设置为失败状态

    #include <iostream> 
    using namespace std; 
    
    int main() 
    { 
        int a; 
        cin >> a; 
        if(!cin)
        {
            cin.clear();
        }
        cout << a << endl; 
        cin >> a; 
        if(!cin)
        {
            cin.clear();
        }
        cout << a << endl; 
    
        return 0; 
    }
    

    【讨论】:

      【解决方案3】:

      a 以未定义的值开头。这不是cin 的错。试试:

      if (cin >> a) {
        cout << a endl;
      }
      

      在使用a之前会检查a的读入是否成功

      【讨论】:

        猜你喜欢
        • 2011-12-07
        • 2014-12-20
        • 1970-01-01
        • 2018-10-11
        • 1970-01-01
        • 2016-01-22
        • 2018-06-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多