应该用C ++链接异常吗? [英] Should exceptions be chained in C++?

查看:155
本文介绍了应该用C ++链接异常吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是以前的问题,但我搜索堆栈,找不到任何真正打击这一点。

This may have been asked previously, but I search the stack and couldn't find any which really hit upon this.

我刚刚完成了一个C ++ - 程序,我已经实现了我自己的异常(虽然派生自std :: exception)。当一个异常导致链式反应,向上传播错误并引发其他异常时,我应用的实践是在模块(读取类)的每个适当步骤连接错误消息。也就是说旧的异常本身被删除,并创建一个新的异常,但是有一个更长的错误消息。

I just finished work on a C++-program where I've implemented my own exceptions (although derived from std::exception). The practice I've applied when one exception causes a chain reaction, propagating the error upwards and giving rise to other exceptions, is to concatenate the error message at each appropriate step across the modules (read classes). I.e. the old exception itself is dropped and a new exception is created, but with a longer error message.

这可能适用于我的小程序,但我不是很满意我的方法到底。对于一个,行号(虽然目前不应用)和文件名不保留除了最后一个异常;并且真正的信息是第一个异常最感兴趣的。

This may have worked for my small program, but I wasn't very satisfied with my approach in the end. For one, line numbers (although not applied at the moment) and file names are not retained except for the last exception; and really that information is of most interest in the first exception.

我认为这可以通过链接异常更好地处理;即在新异常的构造函数中提供旧异常。但是如何实现呢?当异常超出方法范围时,异常是否会死亡,从而阻止使用异常指针?如果异常可以是任何派生类,如何复制和存储异常?

I figure this could have been handled better by chaining exceptions together; i.e. the old exception is provided in the constructor of the new exception. But how would that be implemented? Does not exceptions die when they go out of scope from the method, thereby preventing one to use exception pointers? And how to copy and store the exception if the exception can be of any derived class?

这最终导致我考虑在C ++中链接异常是否是一个好主意所有。也许应该创建一个异常,然后添加额外的数据(像我一直在做,但可能是一个更好的方式)?

This ultimately lead me to consider whether chaining exceptions in C++ is such a good idea after all. Perhaps one should just create one exception and then add additional data to that (like I've been doing, but probably in a much better manner)?

你的回应是什么这个?如果由另一个引起的异常链在一起,以保留一种异常跟踪 - 如何实现? -

What is your response to this? Should exceptions caused by another be chained together to retain a sort of "exception trace" -- and how should that be implemented? -- or should a single exception be used and additional data attached to it -- and how should that be done?

推荐答案

它应该是一个单独的异常和附加的数据如果你希望它超过接收它的 catch 块,除了由$ <$ c $>重新抛出之前,必须将异常对象中的数据复制到链中。 c> throw; 。 (例如,包括 catch 块通过 throw obj; 退出。)

It is necessary to copy the data out of an exception object, into a chain, if you want it to outlive the catch block that receives it, aside from rethrow by throw;. (Which includes, for example, if that catch block exits through a throw obj;.)

这可以通过将数据保存在堆上,并实现 swap move 在C ++ 0x)对你的私人数据里面的异常,例如。

This can be done by putting data to be saved on the heap, and implementing swap (move in C++0x) on your private data inside the exception, for example.

当然,你需要小心使用堆异常...但是再次,在大多数现代操作系统中,内存过度使用完全阻止 new 从未投掷,更好或更糟。

Of course, you need to be careful when using the heap with exceptions… but then again, in most modern OSes, memory overcommitment completely prevents new from ever throwing, for better or for worse. A good memory margin and dropping exceptions from the chain upon complete meltdown should keep it safe.

struct exception_data { // abstract base class; may contain anything
    virtual ~exception_data() {}
};

struct chained_exception : std::exception {
    chained_exception( std::string const &s, exception_data *d = NULL )
        : data(d), descr(s) {
        try {
            link = new chained_exception;
            throw;
        } catch ( chained_exception &prev ) {
            swap( *link, prev );
        } // catch std::bad_alloc somehow...
    }

    friend void swap( chained_exception &lhs, chained_exception &rhs ) {
        std::swap( lhs.link, rhs.link );
        std::swap( lhs.data, rhs.data );
        swap( lhs.descr, rhs.descr );
    }

    virtual char const *what() const throw() { return descr.c_str(); }

    virtual ~chained_exception() throw() {
        if ( link && link->link ) delete link; // do not delete terminator
        delete data;
    }

    chained_exception *link; // always on heap
    exception_data *data; // always on heap
    std::string descr; // keeps data on heap

private:
    chained_exception() : link(), data() {}
    friend int main();
};

void f() {
    try {
        throw chained_exception( "humbug!" );
    } catch ( std::exception & ) {
        try {
            throw chained_exception( "bah" );
        } catch ( chained_exception &e ) {
            chained_exception *ep = &e;
            for ( chained_exception *ep = &e; ep->link; ep = ep->link ) {
                std::cerr << ep->what() << std::endl;
            }
        }
    }

    try {
        throw chained_exception( "meh!" );
    } catch ( chained_exception &e ) {
        for ( chained_exception *ep = &e; ep->link; ep = ep->link ) {
            std::cerr << ep->what() << std::endl;
        }
    }
}

int main() try {
    throw chained_exception(); // create dummy end-of-chain
} catch( chained_exception & ) {
    // body of main goes here
    f();
}

输出(适当地脾气暴躁):

output (appropriately grumpy):

bah
humbug!
meh!

这篇关于应该用C ++链接异常吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆