Оформление обработки ошибок в plain C
От: postmaster  
Дата: 16.06.04 09:41
Оценка:
В свете дискуссии здесь
Автор: Maxim S. Shatskih
Дата: 11.06.04
возник интересный вопрос: как вы оформляете код на plain C, который проверяет возвращаемый код из цепочки вызываемых функций?

Я в своей практике встречал следующие варианты:

1. "Ёлочка":
int f()
{
        int failed;
        void *obj1;
        void *obj2;
        failed = construct_obj1(&obj1);
        if (!failed) {
                failed = construct_obj2(&obj2);
                if (!failed) {
                        failed = do_something(obj1, obj2);
                        // Обработка результатов вызова do_something
                        destruct_obj2(obj2);
                }
                destruct_obj1(obj1);
        }
        return failed;
}

Плюсы:
Минусы:

2. "goto в конец функции":
int f()
{
        int failed;
        void *obj1;
        void *obj2;

        failed = construct_obj1(&obj1);
        if (failed) {
                goto end1;
        }

        failed = construct_obj2(&obj2);
        if (failed) {
                goto end2;
        }

        failed = do_something(obj1, obj2);
        // Обработка результатов вызова do_something

        destruct_obj2(obj2);
end2:
        destruct_obj1(obj1);
end1:
        return res;
}

Плюсы:
Минусы:

3. "выходим сразу":
int f()
{
        int failed;
        void *obj1;
        void *obj2;

        failed = construct_obj1(&obj1);
        if (failed) {
                return failed;
        }

        failed = construct_obj2(&obj2);
        if (failed) {
                destruct_obj1(obj1);
                return failed;
        }

        failed = do_something(obj1, obj2);
        // Обработка результатов вызова do_something

        destruct_obj2(obj2);
        destruct_obj1(obj1);
        return failed;
}

Плюсы:
Минусы:

4. "выделение деструкторов в отдельный блок":

void finallize_f(void* obj1, void* obj2)
{
        if (obj2 != NULL) {
                destruct_obj2(obj2);
        }
        if (obj1 != NULL) {
                destruct_obj1(obj1);
        }
}

int f()
{
        int failed;
        void *obj1 = NULL;
        void *obj2 = NULL;

        failed = construct_obj1(&obj1);
        if (failed) {
                finallize_f(obj1, obj2);
                return failed;
        }

        failed = construct_obj2(&obj2);
        if (failed) {
                finallize_f(obj1, obj2);
                return failed;
        }

        failed = do_something(obj1, obj2);
        // Обработка результатов вызова do_something

        finallize_f(obj1, obj2);
        return failed;
}

Плюсы:
Минусы:

Ну и, напоследок, вариант на C++:
Obj1 obj1;
Obj2 obj2;
do_something(obj1, obj2);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.