处理C中错误的样式?

时间:2011-05-14 21:15:35

标签: c error-handling coding-style

  

可能重复:
  Error handling in C code

大家好。我正在使用C进行一些小项目,我知道如何,因为它没有专门的错误处理结构,我必须用额外的条件块污染我的算法。我的问题是你更喜欢如何处理错误,并说明原因。我在两种方式之间挣扎......如果你有第三种方式,发布它。感谢。

///////////////////////////////////////////
// method 1

// stuff that can go wrong;

if (test1 == failed)
{
    // print error;
    // exit;
}
else
{
    // more stuff that can go wrong;

    if (test2 == failed)
    {
        // print error;
        // exit;
    }
    else
    {
        // ... and so on...
    }
}

///////////////////////////////////////////
// method 2

// stuff that can go wrong;

if (test1 == failed)
{
    // print error;
    // exit;
}

// more stuff that can go wrong;

if (test2 == failed)
{
    // print error;
    // exit;
}

// ... and so on...

4 个答案:

答案 0 :(得分:5)

有些人不同意我这个,但我使用goto的。在每个函数内部,最后我在结尾处有一个块,看起来像这样

if (0)
{
ERROR:
  // Handle errors, and exit/return after potentially freeing resources
}

然后我使用if (something_bad) goto ERROR;没有其他东西。

许多人不喜欢goto,但这是实现此目的而不是复制代码的方法。如果你真的坚持不使用goto,我会这样做:

#define LOCAL_ASSERT(COND) if (COND) { \
  /* Handle errors, and exit/return after potentially freeing resources */ \
}

在每个函数的开头添加一个定义,然后在函数末尾添加#undef LOCAL_ASSERT。这允许在每个函数处进行不同的错误处理,而不会用不同的宏名称污染整个程序。

然后我只是在任何地方使用LOCAL_ASSERT(cond)

编辑:让自己更清楚,这是多次保存写错误处理代码。如果您想要小型自定义,则可以轻松设置错误变量字符串(或将其添加为宏参数)。我根本不喜欢别的东西。我通常做

// method 1
if (error) goto ERROR; // no else

// method 2
LOCAL_ASSERT(cond);

Elses会污染您的代码并需要更多缩进,这有时很烦人。

答案 1 :(得分:1)

我在某种程度上知道它的用户偏好,但我很难从每个函数或最多两个退出点建立单个出口点(但它们必须明显且容易断点) :

const Bool funcFoo(int someval, int someval2, int someval3)
{
  if(someval == okval)
  { // We're ok
    if(someval2 == okval2)
    { // Still ok.
      if(someval3 == okval3)
      { // Yippee!  We made it!
        return True;  // <===== ONLY SUCCESS RETURN POINT
      }
    }
  }
  // Houston, we had a problem.
  return False;  // <===== ONLY FAIL RETURN POINT
}

在“else”很重要的情况下,它是类似的展开,但我们只保留两个返回点:

const Bool funcFoo(int someval, int someval2, int someval3)
{
  if(someval == okval)
  { // We're ok
    if(someval2 == okval2)
    { // Still ok.
      if(someval3 == okval3)
      { // Yippee!  We made it!
        return True;  // <===== ONLY SUCCESS RETURN POINT
      }
      else
      { // someval3 is bad.
        //...maybe handle, not return.
      }
    }
    else
    { // someval2 is bad.
      // ...maybe handle, not return.
    }
  }
  else
  { // someval is bad.
    // ...maybe handle, not return.
  }
  // Houston, we had a problem.
  return False;  // <===== ONLY FAIL RETURN POINT
}

有几件事需要提及:

  1. 一个回归点是最好的。二 如果返回点是可以接受的 显而易见(你的错误通常要求退货,或者不能继续)。
  2. 有时“else”代表 仅用于调试目的,在此处 我将它们包裹在#ifdef _DEBUG ... #endif
  3. 有时候“测试”应该是 成功,有时是失败, 取决于哪个最多 适合筑巢。
  4. 这种方法(嵌套测试)是 有时与顺序相关 测试。但是,嵌套测试是 通常是首选。

答案 2 :(得分:0)

我宁愿使用这样的东西:

if (test1 == failed)
{
    // print error;
    // exit;
}
else if (test2 == failed)
{
    // print error;
    // exit;
}
else
{
    // ... and so on...
}

它更具可读性,它限制了缩进。它还清楚地告诉我,如果一个条件失败,它将尝试所有其他条件,直到它最终失败;没有机会同时满足2个条件。

答案 3 :(得分:0)

我投票支持方法2.正如您所提到的,方法1中的错误处理模糊了“真实”算法的逻辑。