7

使用时boost::exception,知道异常携带什么数据的首选方法是什么?在boost 文档中,给出了以下示例:

catch( io_error & e )
    {
    std::cerr << "I/O Error!\n";

    if( std::string const * fn=get_error_info<file_name>(e) )
        std::cerr << "File name: " << *fn << "\n";

    if( int const * c=get_error_info<errno_code>(e) )
        std::cerr << "OS says: " << strerror(*c) << "\n";
    }

这似乎有点尴尬,特别是如果异常通过很多层冒泡并且理论上有大量可用的元数据。所以我想记录每个异常类的可能错误信息是有意义的。然后我可能还需要一些函数的文档,关于异常中可能包含哪些信息。最后,我觉得我在文档中具有完全相同的结构,如果我只是使用类似以下结构的东西,我会在代码中拥有:

struct FileException {
  string* filename; // NULL or string
}

然后我可以在 catch 块中更改此信息:

catch (FileException& e) {
  e.filename = filename;
  throw;
}

这种简单的方法可以让我绕过大部分文档,并从所有安全性中获益(例如,不尝试从 获取文件名MathException)。然而人们使用boost。我缺少的动态方法有很大的优势吗?您如何在代码中记录错误信息?

4

3 回答 3

1

从非常高的层面,您可以参考该异常的诊断信息:http: //www.boost.org/doc/libs/1_51_0/libs/exception/doc/diagnostic_information.html

这将打印异常携带的所有内容(以及更多内容)。我不确定是否有办法单独获取所有内部内容......

从例子:

example_io.cpp(70): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *)
Dynamic exception type: class boost::exception_detail::clone_impl<struct fopen_error>
std::exception::what: example_io error
[struct boost::errinfo_api_function_ *] = fopen
[struct boost::errinfo_errno_ *] = 2, "No such file or directory"
[struct boost::errinfo_file_name_ *] = tmp1.txt
[struct boost::errinfo_file_open_mode_ *] = rb
于 2014-06-28T20:10:01.720 回答
0

如果您可以更改或设计您的异常以包含描述错误所需的内容,请按照您的意愿进行操作。但是如果您的代码没有生成异常,或者您在生成错误时无权访问错误信息,那么您需要error_info. 例如,假设我们有一个read自由函数,它从一个不包含文件名的 C++ 文件对象中读取数据,如下所示:

void read( file& fp, std::vector<unsigned char>& buf ) {
    if( fread(&buf[0], 1, buf.size(), fp.getFile()) == -1 ) {
        // I don't know the file name, what should I do here??
        boost::throw_exception( io_error() );
    }
}

try {
    file fp( "/path/to/file" );
    // do some thing with fp
    read( fp, buffer );
} catch( io_error& e ) {
    e << file_name( "/path/to/file" ); // here I can provide file name
    throw;
}

正如您所看到error_info的那样,我必须以增量方式将数据添加到错误中,但是如果在抛出站点上我有所有必需的信息,那么我可以将这些信息嵌入到异常类中并避免使用error_info

于 2012-10-03T18:34:24.273 回答
0

“动态方法”的优点是文件名不仅与 FileException 对象相关。例如,如果您打开一个包含数学表达式的脚本文件,该表达式在解析时会引发 MathException,您仍然希望该异常带有文件名。一般来说,throw 站点和 catch 站点之间的调用堆栈无法知道可能通过它的所有可能类型的异常对象,但它通常具有应该存储在其中的相关信息。

于 2016-01-28T20:15:18.770 回答