首页 新闻 赞助 找找看

求大神解释一下以下代码为何在正确捕获异常后会又得到一个异常?update

0
悬赏园豆:20 [已解决问题] 解决于 2017-08-30 18:07
复制代码
struct test
{
    test()
    {
        if (!id)
            throw this;
    }

    int *id = nullptr;
};

struct testex : public test
{
    testex()
        try :test()
    {

    }
    catch (test *t)
    {
        (*t).id = new int(1);
    }
};


int main()
{
    testex t;

    return 0;
}
复制代码

 

求帮忙解释一下,以上代码为何在正确捕获异常后又产生了一个异常?

MyCPlusPlus的主页 MyCPlusPlus | 初学一级 | 园豆:43
提问于:2017-08-28 21:48
< >
分享
最佳答案
1

这个问题比想象中的要深,也是我第一次看到这样的try用法,如果回答有错还请高人指正。
我运行后的异常消息是:
Exception thrown at 0x765CB802 in ConsoleApplication1.exe: Microsoft C++ exception: test at memory location 0x001DF850. (这个是你抛出的异常)
Exception thrown at 0x765CB802 in ConsoleApplication1.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000. (异常在你catch上个异常后,被重新抛出来了,异常原因是访问0地址)
Unhandled exception at 0x765CB802 in ConsoleApplication1.exe: Microsoft C++ exception: test at memory location 0x001DF850. (你没有catch那个被重新抛出来的异常,最后崩溃掉了。)
0x00000000异常的原因应该是父类构造的失败造成导致了`testex`构造的失败,然后这个异常没有被处理,最终导致崩溃。

收获园豆:20
asahi86 | 菜鸟二级 |园豆:242 | 2017-08-29 08:55
int main()
{
    try 
    {
        testex t;
    }
    catch (testex *t)
    {
        std::cout << "testex exception" << std::endl;
    }
    catch (test *t)
    {
        std::cout << "test exception" << std::endl;
    }

    return 0;
}

 

赞成你的说法,但是还有个疑问,我改写main函数如上,但是发现第二次捕获的异常是test而不是testex,

按道理说应该抛出一个testex类型的异常才对。

MyCPlusPlus | 园豆:43 (初学一级) | 2017-08-29 10:11

在你代码里面,是永远不会有类型为testex*的异常的,因为你只有一个显式的throw,其类型为test*。

因为构造的失败,你在`test`构造的异常被重新抛出了,然后这个重新抛出异常被你外围的`catch (test *t)`捕捉到了。

asahi86 | 园豆:242 (菜鸟二级) | 2017-08-30 11:39

@asahi86: 我又做了几个实验,确实是重新抛出了我显示的throw, 这有点让我怀疑这种try用法是否实用,从这个例子看,无论在构造函数里怎么catch,都会重新抛出异常,而且只有在最外层调用的时候catch才能避免这个问题。

MyCPlusPlus | 园豆:43 (初学一级) | 2017-08-30 18:06
其他回答(2)
0

是什么异常,把你的异常截图上来看看。

码农改变世界lyf | 园豆:46 (初学一级) | 2017-08-28 22:07
0

构造函数一样,一般实践是要避免的 Effective C++系列等都有讲解具体的原因

(*t).id = new int(1); 第二次异常,估计是*t是个空,所以其id无法取到

2012 | 园豆:21228 (高人七级) | 2017-08-29 08:34

 在catch的时候,t作为异常消息还没有被销毁,就算没有做catch里面的逻辑仍然会有一样的二次异常。

支持(0) 反对(0) asahi86 | 园豆:242 (菜鸟二级) | 2017-08-29 08:46

@asahi86: 不对id做处理的时候也会有异常,所以应该不是*t是空的问题,但是t作为异常对象是一个指针,应该不会销毁t指的对象,而是对t这个指针做了个拷贝,结束后销毁了这个指针,但这样也不应该会产生异常。

支持(0) 反对(0) MyCPlusPlus | 园豆:43 (初学一级) | 2017-08-29 10:09
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册