使用boost::exception
时,了解异常所携带的数据的首选方法是什么?在boost documentation中给出了以下示例:
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
获取文件名)。然而人们使用提升。我缺少动态方法的一大优势吗?如何记录代码中的错误信息?
答案 0 :(得分: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
答案 1 :(得分: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
设计的情况,我必须逐步向错误添加数据,但如果在throw网站上我有所有必需的信息,那么我可以在异常类中嵌入这些信息并避免使用{{1 }}
答案 2 :(得分:0)
&#34;动态方法的优势&#34;是文件名不仅仅与FileException对象相关。例如,如果您打开一个包含数学表达式的脚本文件,该数据表达式在解析时会抛出MathException,您仍然希望该异常带有文件名。通常,throw站点和catch站点之间的调用堆栈无法知道可能通过它的所有可能类型的异常对象,但它通常具有应存储在其中的相关信息。