提升异常的错误信息

boost exception's error info

本文关键字:错误 信息 异常      更新时间:2023-10-16

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

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 (FileException& e) {
e.filename = filename;
throw;
}

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

从非常高的级别,您可以参考该异常的诊断信息: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

如果您可以更改或设计异常以包含描述错误所需的内容,请根据需要执行。但如果异常不是由您的代码生成的,或者您在生成错误时无法访问错误信息,那么您需要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

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