【问题标题】:Pretty confused about C++ Exception Handling对 C++ 异常处理很困惑
【发布时间】:2017-10-04 08:48:37
【问题描述】:

试图在我的 C++ 程序中添加异常处理,但我发现它很混乱。程序将值 i 和 j 设置为它们的最高可能值并递增它们。我想我希望异常处理能够在整数溢出/环绕发生时检测到它(?)

到目前为止,这是我所拥有的:

#include <iostream>
#include <limits.h>
#include <exception>
#include <stdexcept>
using namespace std;

int main() {
    int i;
    unsigned int j;

    try{
            i = INT_MAX;
            i++;
            cout<<i;
    }
    catch( const std::exception& e){
    cout<<"Exception Error!";
    }   


    try{
            j = UINT_MAX;
            j++;
            cout<<j;
    }
    catch(const std::exception& e){
    cout<<"Exception Error!";
    }
}

程序运行,但异常处理部分不起作用。

可能是什么问题?

【问题讨论】:

  • 问题是没有指定溢出来抛出异常。因此,如果您期待它,那么您对 ​​C++ 有误解。
  • 无符号整数溢出以明确定义的方式环绕。有符号整数溢出会导致undefined behavior,这可能会也可能不会导致回绕,得到一个很大的负数,从而导致崩溃、异常或什至什么都没有发生。

标签: c++ visual-c++ exception-handling integer-overflow


【解决方案1】:

好吧,将i 增加超过INT_MAX 的行为是未定义。那是因为它是有符号整数类型。在这种情况下,我从未遇到过引发异常的实现。 (典型的行为是环绕INT_MIN,但不要依赖它。)

UINT_MAX 之外增加j 必须 环绕到0。那是因为它是unsigned 类型。也就是说,必须绝不抛出异常。

【讨论】:

  • 我可以想到三种可能的签名溢出实现,所有这些都比抛出异常更有可能:1.环绕,2.饱和INT_MAX,3.进程被杀死一个信号。
  • @Downvoter,如果我说了什么傻话,请发表评论。
  • 我怎样才能发现这种情况是 undefined ?你能分享一个可靠的来源吗?
【解决方案2】:

C++ 没有定义在整数溢出的情况下要抛出的任何异常。如果您想实现这样的行为,您将需要一些具有相应功能的整数类包装器,例如Safe Int library。示例:

#include <safeint.h>

#include <iostream>

int main()
{
    try
    {
        ::msl::utilities::SafeInt<int> j;
        for(;;)
        {
            ++j;
        }
    }
    catch(::msl::utilities::SafeIntException const & exception)
    {
        switch(exception.m_code)
        {
            case ::msl::utilities::SafeIntArithmeticOverflow:
            {
                ::std::cout << "overflow detected" << ::std::endl;
                break;
            }
            default:
            {
                break;
            }
        }
    }
    return(0);
}

【讨论】:

  • “C++ 确实会抛出任何异常......”。我怀疑你需要“不”这个词。
  • @Peter:这两种情况都不是绝对正确的。签名的案例是 UB,当然,它可以通过抛出异常来表现出来。但尽管如此,我认为作者的意图是你如何描述它。所以我做了一个编辑。
  • @Bathesda - 无论哪种方式,C++ 标准都不需要抛出异常。
  • @Peter:当然。这不是我说的吗?
【解决方案3】:

在 C++ 中,异常不只是发生。 throw 关键字抛出异常;如果您的代码(或您链接到的代码)没有throw something(),它不会引发异常。

然而,这并不完全正确:在某些奇怪的情况下,代码做了一些不恰当的事情(正式地,代码具有未定义的行为),这可能导致抛出异常。这超出了语言定义的规则,因此不可移植且不可靠(是的,我在看你,Windows SEH)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多