我遇到过几个问题,但没有找到答案。
我想知道如何在C ++软件中实现异常处理,使其集中化并跟踪软件进度?
例如,我想在程序的四个阶段处理异常,并知道异常发生在该特定阶段:
1.初始化
2.脚本处理
3.计算
4.总结。
此时,我尝试了这个:
int main (...)
{
...
// start logging system
try {
...
}
catch (exception &e)
{
cerr << "Error: " << e.what() << endl;
cerr << "Could not start the logging system. Application terminated!\n";
return -1;
}
catch(...)
{
cerr << "Unknown error occured.\n";
cerr << "Could not start the logging system. Application terminated!\n";
return -2;
}
// open script file and acquire data
try {
...
}
catch (exception &e)
{
cerr << "Error: " << e.what() << endl;
cerr << "Could not acquire input parameters. Application terminated!\n";
return -1;
}
catch(...)
{
cerr << "Unknown error occured.\n";
cerr << "Could not acquire input parameters. Application terminated!\n";
return -2;
}
// computation
try {
...
}
...
这绝对不是集中的,而且看起来很愚蠢。 或者它根本不是一个好概念?
答案 0 :(得分:3)
您可以保留一个包含程序状态的全局变量,并将其打印在catch块中。那么你只需要两个catch块,一个用于std :: exception,另一个用于其他一切。
答案 1 :(得分:2)
在我看来,您尝试使用异常(或多或少)替代日志记录。我想在这种情况下,将两者结合起来会好得多 - 特别是,我可能有一个小的异常处理程序将输出放在日志中,所以你的代码看起来像这样:
try {
// start logging system
}
catch (exception const &e) { std::cerr << e.what << "error starting logging"; }
catch (...) { std::cerr << "Unknown error starting logging"; }
try {
{ scoped_log("script processing");
start_script();
}
{ scoped_log("computation");
do_computation();
}
{ scoped_log("wrap up");
wrap_up();
}
}
catch(std::exception const &e) { log << "error: " << e.what() << "\n"; }
catch(...) { log << "Unknown exception\n"; }
其中“scoped_log”是一个简单的类,如:
class scoped_log {
std::string caption;
public:
scoped_log(std::string const &c) : caption(c) {
log << "Starting: " << caption << "\n";
}
~scoped_log() { log << "Finished: " << caption << "\n"; }
};
这允许您集中大多数的异常处理。唯一的例外(没有双关语)是启动日志系统本身 - 显然你不能使用日志来报告启动日志系统的问题。
然而,一旦日志系统启动,事情就会简单得多 - 您可以使用日志记录和异常处理的组合来跟踪问题发生的时间。记住一个小细节:因为scoped_log
是一个在退出范围时被破坏的对象(出于任何原因),所以日志的结构可能(至少在最初阶段)看起来有点误导 - 错误消息将跟随日志中的“finshed xxx”消息。例如,如果无法打开脚本文件,则您的日志可能如下所示:
starting script processing
finished script processing
error: could not open file: 'script.input'
至少IMO,如果你意识到这种情况,这不太可能导致问题。
答案 2 :(得分:1)
在我看来,例外情况应该(通常)有5个条件:
答案 3 :(得分:1)
集中异常处理的一种简单方法是创建一个简单的函数来处理异常,然后使用调用函数的泛型catch:
void processExceptions( std::string const & stage )
{
std::cout << "Exception caught at stage " << stage << std::endl;
try {
throw; // rethrow the last caught exception
}
catch ( exception1 const & ) {
// do process 1
}
catch ( exception2 const & ) {
// ...
}
}
int main()
{
try {
initialize();
}
catch ( ... ) {
processExceptions( "initialization" );
}
try {
stage2();
}
catch ( ... ) {
processExceptions( "stage2" );
}
}
我从未使用过这种技术来识别异常何时被捕获,但如果相同的话,避免在许多地方重复异常处理代码是非常有用的。
请注意,如果在没有抛出异常的情况下调用该函数(在catch之外),您将得到未定义的行为,并且通常情况下您的应用程序将会死亡。
答案 4 :(得分:0)
另一种选择是具有不同的,由您定义的异常,然后您可以在一个中心位置处理,而不是使用不同的返回值。因此,当“无法获取输入参数”之类的异常发生时,您会抛出类似“invalid_parameters exception”的内容,并添加一些关于异常原因的更多上下文信息。然后在中央位置显示错误。
答案 5 :(得分:0)
如果您真的想要更集中化,可以定义自己的错误类,例如
class does_not_open {};
class cannot_write {};
左右。你需要在不同的部分做更多的工作,例如,检查开放是否成功;如果没有,抛出does_not_open(等等)。但是在以这种方式组织自己之后,您可以将代码的整个主要部分放入以下形式:
try{
}
catch(does_not_open &e){
}
catch(cannot_write &e){
- your code here -
}
catch(...){
- your code here -
}
不确定这会达到你所希望的......但是gl。 :)