当我为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吗?
答案 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,那么它可能是有意义的。否则,不是那么多。在实际需要时添加异常处理。