【问题标题】:Correct method to test for errors and cleanup before return [closed]返回前测试错误和清理的正确方法[关闭]
【发布时间】:2012-10-01 12:40:03
【问题描述】:

编码风格而言,以下两种实现中哪一种更好,为什么?

UINT Fn1()
{
    HKEY hRegKey;

    if(RegOpenKeyEx(..., KEY_NAME, &hRegKey) != ERROR_SUCCESS)
        return ERROR_KEY_OPEN;
    if(RegQueryValueEx(hRegKey, VAL_A_NAME, ...) != ERROR_SUCCESS)
    {
        RegCloseKey(hRegKey);
        return ERROR_KEYVAL_A;
    }

    if(RegQueryValueEx(hRegKey, VAL_B_NAME, ...) != ERROR_SUCCESS)
    {
        RegCloseKey(hRegKey);
        return ERROR_KEYVAL_B;
    }

    RegCloseKey(hRegKey);
    return ERROR_SUCCESS;
}

UINT Fn2()
{
    UINT rVal;
    HKEY hRegKey;

    if(RegOpenKeyEx(..., KEY_NAME, &hRegKey) == ERROR_SUCCESS)
    {
        if(RegQueryValueEx(hRegKey, VALUE_A_NAME, ...) == ERROR_SUCCESS)
        {
            if(RegQueryValueEx(hRegKey, VALUE_B_NAME, ...) == ERROR_SUCCESS)
                rVal = ERROR_SUCCESS;
            else
                rVal = ERROR_KEYVAL_B;
        }
        else
            rVal = ERROR_KEYVAL_A;
        RegCloseKey(hRegKey);
    }
    else
        rVal = ERROR_KEY_OPEN;

    return rVal;
}

另外,还有更好的方法吗?
注意:请不要混淆 sn-p 的细节 - 强调代码流和样式。

【问题讨论】:

  • 这个答案对于 C 或 C++ 会有所不同,但你已经标记了两者。此外,这是一个相当主观的问题。
  • 请回答 - 对于通用场景。我没有将问题转换为更通用的形式以使其更真实。
  • 之前有人问过这个问题:HereProgrammers.SE。这两次,回答者都更喜欢“提前返回”(即您的第一个版本)
  • @ArjunShankar 感谢您的指点。但这种情况与返回前所需的clean-up 不同。我已经修改了我的问题,我认为对于其他有类似疑问的人来说,它仍然是useful

标签: c coding-style error-handling return


【解决方案1】:

这在很大程度上是个人喜好问题。我个人会说既不好看也不容易理解。我个人比较喜欢的C语言形式是:

int
fn(void)
{
    struct foo *foo;
    int error = 0;
    if ((foo = foo_open(...)) == NULL)
        return FOO_ERROR_OPEN;
    if (foo_do_something(1)) {
        error = FOO_ERROR_1;
        goto out;
    }
    if (foo_do_something(2)) {
        error = FOO_ERROR_2;
    }
out:
    foo_close(foo);
    return error;
}

但如前所述,这是一个品味问题,并且有多少程序员对此有多少意见。我更喜欢这种风格,因为这是我在职业生涯早期使用的大量代码的编写方式,并且这使它对我来说最易读。

如果我必须选择您提供的一种样式,我会选择 1,因为 2 看起来很乱,因为压痕很深。我的经验法则是可读性随着缩进深度而降低。

【讨论】:

  • 嗯,是的,goto 在这里是个不错的选择。
  • @UjjwalSingh 用一个资源来释放它大多是矫枉过正,但是当你最终在一个函数中持有三个锁和五个临时分配的内存块时,goto 真的可以解决问题。
  • 你是对的 - 我以第一个结尾。
猜你喜欢
  • 1970-01-01
  • 2013-07-05
  • 2013-02-27
  • 1970-01-01
  • 2017-04-18
  • 2015-03-05
  • 1970-01-01
  • 2014-06-19
  • 2019-09-17
相关资源
最近更新 更多