0

__tryWindows 用の C コードをプログラミングするとき、SEH の...ブロックを使用するように「デフォルト」する__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);

明確化

私は言及するのを忘れました:

My idea behind this was that, if someone inserts more code later into the block (e.g. an early return from the function), my code would still perform the cleanup, rather than exiting prematurely. So it was supposed to be more preventive than anything else. Should I still avoid using SEH anyway?

4

3 に答える 3

3

私の意見では、いいえ。マイナス面は余分な__try/__finallyノイズが多く、プラス面が何であるかわかりません.

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

これらが失敗することをどのように期待していますか?たとえば、SEH 例外を発生させるのではなく、(チェックしない) をSelectObject返すことによってエラーを報告します。NULLSEH 例外の多くのインスタンスは、回復できない基本的なエラーを示しています (メモリが破損しているか、無効なハンドルを関数などに渡すなどの論理エラーが発生しています)。この種のエラーは正常に処理できず、通常はクラッシュの方がデバッグが容易です。

早期の返品に直面してもコードを堅牢にしたい場合 (多くの C コーディング標準では、このような理由で推奨されていません)、危険な方法で変更するのがより困難な方法でコードを構造化することを検討する必要があります。例えば

int f()
{
    int ret;
    Resource r;

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

    ret = FunctionWithLogicAndEarlyReturns(&r);

    CleanupResource(&r);
    return ret;
}

この関数は単純であるため、追加の初期リターンを追加する誘惑はほとんどなく、呼び出された「ロジック」関数の初期リターンが取得したリソースのクリーンアップに害を及ぼさないことを期待できます。

于 2012-02-04T23:07:01.500 に答える
1

そのようなコードが例外をスローする場合、システムはおそらく、リソースを正しく解放するかどうかは問題にならないか、まったく解放できない (またはその両方) 状態にあります。個人的にはこれらを使用しません。ノイズが追加され、コードが奇妙に見えるだけです。MSDN の例でもそれらを使用していません (SEH 自体について説明している場合のみ)。また、WINAPI でのエラー処理は、戻り値と out パラメータに基づいています。

あなたの更新について: この場合、私は YAGNI が適用されると強く信じています。もちろん、正確なアプリケーションによって異なります。SEH を必要とするコードが存在することが事前にわかっている場合は、それが理にかなっている可能性があります。そうでなければ、それほどではありません。実際に必要なときに例外処理を追加します。

于 2012-02-04T23:11:50.410 に答える
1

私はあなたの例のどちらも使用しません。SEH は使用せず、関数の戻り値を確認します。

「hDCCompat の元のビットマップの保存と復元にも失敗しました。

于 2012-02-04T23:03:36.307 に答える