How to deal with constant error checking in C?

84 Views Asked by At

In C, I am calling many functions having to check if they worked. The code gets ~3x bigger because of it! An example:

char *myStr = malloc(sizeof(char));
if (!myStr)
    return NULL;

Is there a more readable way to code calling and error-checking in C? Or is this just the way the cookie crumbles?

I have tried the following macro. But it does not seem idiomatic in C, nor it worked -- the mistake was pointed by "Key Y-N".

#define TRY_EXCEPT(try_statement, except_condition, except_statement) try_statement##if(except_condition){except_statement}

Edit: This is the density of calling and error-checking I meant.

if (!varNames)
    goto exit_fail;

struct dynStr *asmCode = dynStr_create();
if (!asmCode)
    goto exit_fail;

int rc;
rc = dynStr_append(asmCode, ".data\n");
if (!rc)
    goto exit_fail;

char *varName;
for (size_t i = 0; (varName = daStr_getString(varNames, i)); i++) {
    rc = dynStr_append(asmCode, "DD ");
    if (!rc)
        goto free_and_exit;

    rc = dynStr_append(asmCode, varName);
    if (!rc)
        goto free_and_exit;

    rc = dynStr_append(asmCode, "\n");
    if (!rc)
        goto free_and_exit;
}
2

There are 2 best solutions below

3
Harith On

I'd condense it like so:

if (!(rc = dynStr_append(asmCode, "DD ")) 
    || !(rc = dynStr_append(asmCode, varName)) 
    || !(rc = dynStr_append(asmCode, "\n"))) {
    goto free_and_exit;
}

Or use another variable:

int exit_stat = !(rc = dynStr_append(asmCode, "DD ")) 
                || !(rc = dynStr_append(asmCode, varName)) 
                || !(rc = dynStr_append(asmCode, "\n"));

if (exit_stat) {
    goto free_and_exit;
}

Or simply remove the assignment to rc:

if (!dynStr_append(asmCode, "DD ")) 
    || !dynStr_append(asmCode, varName) 
    || !dynStr_append(asmCode, "\n"))) {
    goto free_and_exit;
}
2
Fe2O3 On

You can economise by recognising the LF is not so special. (And, pay attention to where you branch after a presumed dynamic allocation.)

struct dynStr *asmCode = dynStr_create();
if (!asmCode)
    goto exit_fail;

if( !dynStr_append(asmCode, ".data") )
    goto free_and_exit; // memory leak fixed...

char *varName;
for( size_t i = 0; (varName = daStr_getString(varNames, i)); i++ ) {
    if( !dynStr_append(asmCode, "\nDD ") // Notice the LF prepended
    ||  !dynStr_append(asmCode, varName) )
        goto free_and_exit;
}
if( !dynStr_append(asmCode, "\n") )
    goto free_and_exit;