es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Mejores prácticas para salida no local con limpieza en C

¿Cuál se considera la mejor práctica para abortar en caso de errores en C?

En nuestra base de código, actualmente tenemos un patrón utilizando

#define CHECKERROR(code) if(code) { return code; }

pero esto ocasiona que los recursos no se cierren en el código de la forma siguiente

/* no es código real debido a restricciones de confidencialidad */
int somefunction() {
    handle_t res1, res2;
    int errorcode;

    res1 = getResource();
    res2 = getResource();

    errorcode = action1(res1, res2);
    CHECK(errorcode);
    errorcode = action2(res1, res2);
    CHECK(errorcode);

    freeResource(res1);
    freeResource(res2);
    return errorcode;
}

Me encontré con el patrón en artículos anteriores,

/* inicializar recursos */
do {
    /* ... */
    errorcode = action();
    if(errorcode) break;
    /* ... */
} while(0);
/* limpiar recursos */
return errorcode;

pero no pude encontrar ninguna fuente que lo discutiera ahora.

¿Cuál es una buena práctica que se consideraría idiomática en C? ¿El patrón do { } while(0); califica como tal? ¿Existe alguna forma idiomática de hacerlo más claro, que no sea una iteración, sino un bloque con salida no local?

Tags:  ,

Answer

  1. Avatar for davy.ai

    La mejor práctica para abortar en caso de errores en C implica manejar correctamente los recursos, como liberar la memoria asignada o cerrar archivos abiertos. Si bien la macro CHECKERROR puede ser útil para salir rápidamente de una función en caso de error, no se encarga del manejo de recursos.

    Un enfoque mejor es utilizar un bloque do { } while(0); para asegurar el manejo adecuado de los recursos, como se muestra en el código de ejemplo. Este patrón permite una fácil limpieza de los recursos antes de devolver un código de error. Sin embargo, es importante tener en cuenta que este bloque no debe tratarse como un bucle, sino como un bloque con salida no local.

    Para que la intención del bloque do { } while(0); sea más clara, se recomienda agregar un comentario que especifique explícitamente su propósito, como se muestra a continuación:

    /* inicializar recursos */
    do {
        /* ... */
        errorcode = action();
        if(errorcode) break;
        /* ... */
    } while(0); /* fin del bloque de recursos */
    
    /* limpiar recursos */
    return errorcode;
    

Comments are closed.