Должен ли я использовать SEH "по умолчанию" в C? - PullRequest
0 голосов
/ 05 февраля 2012

Когда я программирую код на C для Windows, должен ли я "по умолчанию" использовать блоки __try ... __finally SEH, или это считается плохой практикой, делать это без необходимости?

ВДругими словами, какое из приведенных ниже (например) считается лучшей практикой и почему?

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 ]

3 голосов
/ 05 февраля 2012

На мой взгляд, нет. Недостатком является много дополнительного __try / __finally шума, и я не вижу, что это такое.

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

Как вы ожидаете, что они потерпят неудачу? Например, SelectObject сообщает об ошибке, возвращая NULL (который вы не проверяете), а не вызывая исключение SEH. Многие экземпляры исключений SEH указывают на фундаментальную ошибку, которую невозможно исправить (вы испортили память или допустили логическую ошибку, например, передали недопустимый дескриптор функции или чему-то еще). Ошибки такого рода не могут быть обработаны изящно, и сбой обычно легче отладить.

Если вы хотите сделать свой код устойчивым перед лицом ранних возвратов (что во многих стандартах кодирования C не способствует, отчасти по этой причине), тогда вам следует рассмотреть возможность структурирования кода таким образом, чтобы его было сложнее модифицировать в опасном пути. Э.Г.

int f()
{
    int ret;
    Resource r;

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

    ret = FunctionWithLogicAndEarlyReturns(&r);

    CleanupResource(&r);
    return ret;
}

Вы можете надеяться, что, поскольку эта функция проста, будет мало соблазна добавить дополнительные ранние возвраты, ранние возвраты в вызываемой «логической» функции не повредят очистке полученного ресурса.

1 голос
/ 05 февраля 2012

Если такой код вызывает исключение, система, вероятно, находится в состоянии, в котором либо не имеет значения, правильно ли вы освободили ресурсы, либо вы не можете вообще (или оба). Лично я бы не использовал их, они просто добавляют шум и делают ваш код странным. Примеры MSDN также не используют их (только там, где обсуждается сама SEH). Кроме того, обработка ошибок в WINAPI основана на возвращаемых значениях и выходных параметрах.

По поводу вашего обновления: в этом случае я твердо верю, что YAGNI применяется. Конечно, это зависит от конкретного приложения, и если вы заранее знаете, что будет код, который нуждается в SEH, то это может иметь смысл. Иначе не так уж и много. Добавьте обработку исключений, когда вам это действительно нужно.

1 голос
/ 05 февраля 2012

Я бы не использовал ни один из ваших примеров. Я бы не использовал SEH и проверял бы возвращаемые значения функций.

Вам также не удалось сохранить и восстановить исходное растровое изображение hDCCompat.

...