如何处理错误

时间:2012-02-06 17:49:09

标签: c design-patterns error-handling

我想知道在编程中处理错误的最佳方法是什么(我用C编码)。我是程序员的新手,这就是我正在做的事情:

if( action1 was successfull )
{
   [some code]
   if (action 2 was successfull)
   {
      [some more code ..]
      if (action 3 was successfull)
      {
         ETC ... 
      }
      else
      {
        [Handle error3]
      }
   }
   else
   {
     [handle error2]
   }
}
else
{
  [Handle error1]
}

但我认为这是一个糟糕的习惯......有人可以向我解释一下,最优雅的方式是什么? 感谢

3 个答案:

答案 0 :(得分:4)

我这样做:

// more code
if (!action_1_succeeded())
{
   handle_error();
   return;
}

// more code
if (!action_2_succeeded())
{
   handle_error();
   return;
}

// more code
if (!action_3_succeeded())
{
   handle_error();
   return;
}

通常,我会将handle_errorreturn打包成一个宏,所以我只做check_error(some_statement());

答案 1 :(得分:4)

有时候你展示的代码确实是最好的选择,但这里有一些选择。

通常你可以这样构建你的代码:

if (action_1() failed) {
    report error;
    return -1;
}
if (action_2() failed) {
    report error;
    return -1;
}
/* etc */

这个结构就是为什么在成功时返回0或在失败时返回-1的常见C语言:它允许你将if (action_1() failed)写为if (action_1())

如果你需要在返回之前进行一些清理,并且清理行动整齐地嵌套,这是另一种可能性:

if (action_1()) {
    report error;
    goto fail_a1;
}
if (action_2()) {
    report error;
    goto fail_a2;
}
if (action_3()) {
    report error;
    goto fail_a3;
}
/* etc */
return 0;

/* errors */
/* etc */
fail_a3:
  clean up from a2;
fail_a2:
  clean up from a1;
fail_a1:
  return -1;

特此授权您使用goto来执行此操作。

答案 2 :(得分:1)

您可以创建错误ID并将错误处理程序与特定类型的错误相关联。

typedef struct _error {
  void (*handler)(struct _error *); 
  int i_params;
  char *c_params;
} error;

void nope(error * e) {}
void file_err(error * e) { exit(1); }

error handlers[200];

void check_error(int id) {
  handlers[id].handler(&handlers[id]);
}

enum error { ER_SUCCESS, ER_FILE};
int main() {
  handlers[ER_SUCCESS].handler = nope;
  handlers[ER_FILE].handler = file_err;
  check_error(action1());
  return 0;
}