我应该在C中“默认”使用SEH吗?

时间:2012-02-04 22:51:10

标签: c windows seh

当我为Windows编写C代码时,我应该“默认”使用SEH的__try ... __finally块,还是不必要地执行此操作被认为是不好的做法?

换句话说,下面哪一个(例如)被认为是更好的做法,为什么?

HDC hDCCompat = CreateCompatibleDC(hDC);
__try
{
    HBITMAP hBmpCompat = CreateCompatibleBitmap(hDC, ...);
    __try
    {
        SelectObject(hDCCompat, hBmpCompat);
        BitBlt(hDC, ..., hDCCompat, ...);
    }
    __finally { DeleteObject(hBmpCompat); }
}
__finally { DeleteObject(hDCCompat); }

HDC hDCCompat = CreateCompatibleDC(hDC);
HBITMAP hBmpCompat = CreateCompatibleBitmap(hDC, ...);
SelectObject(hDCCompat, hBmpCompat);
BitBlt(hDC, ..., hDCCompat, ...);
DeleteObject(hBmpCompat);
DeleteObject(hDCCompat);

澄清

我忘了提及:

我的想法是,如果有人稍后在块中插入更多代码(例如从函数中提前返回),我的代码仍会执行清理,而不是过早退出。所以它应该比其他任何东西更具预防性。我还应该避免使用SEH吗?

3 个答案:

答案 0 :(得分:3)

在我看来,没有。缺点是额外的__try / __finally噪音很多,我看不出它的优点。

SelectObject(hDCCompat, hBmpCompat);
BitBlt(hDC, ..., hDCCompat, ...);

您对这些失败有何看法?例如,SelectObject通过返回NULL(您未检查)而不是通过引发SEH异常来报告错误。 SEH异常的许多实例表明一个不可恢复的基本错误(您已经损坏了内存,或者您发出了一个逻辑错误,例如将无效句柄传递给函数或其他东西)。无法正常处理这些类型的错误,并且通常更容易调试崩溃。

如果你想让你的代码在早期返回(许多C编码标准不鼓励,部分由于这个原因)的情况下使代码变得健壮,那么你应该考虑以一种在危险中更难修改的方式构建代码方法。 E.g。

int f()
{
    int ret;
    Resource r;

    if (!AcquireResource(&r))
        return FAIL;

    ret = FunctionWithLogicAndEarlyReturns(&r);

    CleanupResource(&r);
    return ret;
}

你可以希望,因为这个函数很简单,所以很少会有额外的早期回报,所谓的“逻辑”函数的早期回报不会损害所获资源的清理。

答案 1 :(得分:1)

我不会使用你的任何一个例子。我不会使用SEH,我会检查函数的返回值。

您也无法保存和恢复'hDCCompat的原始位图。

答案 2 :(得分:1)

如果此类代码抛出异常,系统可能处于这样一种状态,即如果您正确释放资源,或者根本不可能(或两者都有),则无关紧要。就个人而言,我不会使用这些,他们只是添加噪音,让你的代码看起来很奇怪。 MSDN示例也不使用它们(仅在它讨论SEH本身的地方)。此外,WINAPI中的错误处理基于返回值和输出参数。

关于您的更新:在这种情况下,我坚信YAGNI适用。当然,这取决于确切的应用程序,如果您事先知道会有需要的代码 SEH,那么它可能是有意义的。否则,不是那么多。在实际需要时添加异常处理。