Есть ли какой-нибудь другой способ справиться со многими ошибками malloc?

Я пытаюсь написать функцию на C для решения математической задачи. В этой функции есть несколько шагов, и на каждом шаге необходимо выделить некоторую память с размером в зависимости от результатов вычислений на предыдущих шагах (поэтому я не могу выделить их все в начале функции). Псевдокод выглядит так:

int func(){
    int *p1, *p2, *p3, *p4;
    ...

    p1 = malloc(...);
    if(!p1){
        return -1;            //fail in step 1
    }

    ...
    p2 = malloc(...);
    if(!p2){
        free(p1);
        return -2;            //fail in step 2
    }

    ...
    p3 = malloc(...);
    if(!p3){
        free(p1);
        free(p2);
        return -3;            //fail in step 3
    }

    ...
    p4 = malloc(...);
    if(!p4){
        free(p1);
        free(p2);
        free(p3);            /* I have to write too many "free"s here! */
        return -4;           //fail in step 4
    }

    ...
    free(p1);
    free(p2);
    free(p3);
    free(p4);

    return 0;                //normal exit
}

Вышеупомянутый способ обработки ошибок malloc ужасен. Таким образом, я делаю это следующим образом:

int func(){
    int *p1=NULL, *p2=NULL, *p3=NULL, *p4=NULL;
    int retCode=0;
    ...

    /* other "malloc"s and "if" blocks here */

    ...
    p3 = malloc(...);
    if(!p3){
        retCode = -3;            //fail in step 3
        goto FREE_ALL_EXIT;
    }

    ...
    p4 = malloc(...);
    if(!p4){
        retCode = -4;            //fail in step 4
        goto FREE_ALL_EXIT;
    }

    ...
FREE_ALL_EXIT:
    free(p1);
    free(p2);
    free(p3);
    free(p4);

    return retCode;              //normal exit
}

Хотя я считаю, что теперь он стал более кратким, ясным и красивым, мой товарищ по команде все еще категорически против использования 'goto'. И он предложил следующий метод:

int func(){
    int *p1=NULL, *p2=NULL, *p3=NULL, *p4=NULL;
    int retCode=0;
    ...

    do{

        /* other "malloc"s and "if" blocks here */

        p4 = malloc(...);
        if(!p4){
            retCode = -4;            //fail in step 4
            break;
        }

    ...     
    }while(0);

    free(p1);
    free(p2);
    free(p3);
    free(p4);

    return retCode;              //normal exit
}

Хммм,кажется способ избежать использования 'goto', но этот способ увеличивает отступы, что делает код некрасивым.

Итак, мой вопрос: есть ли какой-либо другой метод для обработки многих сбоев 'malloc' в хороший стиль кода? Спасибо всем.

5
задан Stan 20 July 2011 в 01:09
поделиться