views:

166

answers:

6

Hi All,

I want to know if check for return codes for all of functions that we write for production environment. for e,g, i use C a lot and do u catch the return codes for the standard library also, not just the functions that you write , but the 3rd party API/standard library/any other library.

Most code i see in production do not do this. So my question is to the experienced people who have worked in production environments and have been writing production code for like 20 years or so. Do you catch return code from 3rd party API/standard library/any other library, and not just the functions that you implement? just to give an e.g of what i mean say do you catch return codes for the C standard lib functions(snprintf/sprintf,strncat/strcat and so on..,..) of C standard library.

Thanks for all your replies.

+2  A: 

I don't think you should take an all-or-nothing approach to this. Capture return/error codes when you expect problems with the function call (or, of course, if your subsequent computation depends on what the function returns). However, if you are pretty sure the call cannot result in errors (or you have no use for the return value even otherwise), do skip capturing the return value.

This is one of those areas where an individual's engineering judgment, not some prescribed "best practice", is to be relied on. Also, the same thinking I believe would apply to exception handling.

Frederick
yes so its more of an art ..rather than science...
Strongly disagree. With very few exceptions, you should always check return codes, even if you don't expect problems. Because sometimes problems occur where you didn't expect them. And debugging a problem that results from an undetected failure elsewhere can be a nightmare...
sleske
Very dangerous method: "all programmers are optimistic" They always think that an error cannot occur and, when it does.... I vote for checking.
bortzmeyer
A: 

snprintf is useful, as you may want to allocate a larger buffer then retry, or you may be calling it in a sequence:

// cons lists as [a,b,c, ...]
if ( type == kin_cons_class() ) {
    size_t offs = snprintf ( buf, max, "[" );

    if ( offs >= max )
        return nul_terminate ( buf, offs, max );

    size_t count = depth;

    kin_cons_ref_t empty = kin_cons_nil();
    kin_cons_ref_t cons;

    for ( cons = ref; cons != empty; cons = kin_cons_tail ( cons ) ) {
        if ( count > 15 ) {
            offs += snprintf ( buf + offs, max - offs, ", ..." );

            break;
        }

        if ( cons != ref ) {
            offs += snprintf ( buf + offs, max - offs, "," );

            if ( offs >= max )
                return nul_terminate ( buf, offs, max );
        }

        offs += string_repr ( buf + offs, max - offs, kin_cons_head ( cons ), depth, escape_strings );

        if ( offs >= max )
            return nul_terminate ( buf, offs, max );

        ++count;
    }

    if ( offs >= max )
        return nul_terminate ( buf, offs, max );

    offs += snprintf ( buf + offs, max - offs, "]" );

    return nul_terminate ( buf, offs, max );
}

If you keep going without all the offs >= max tests, you get a buffer overflow and it will segfault.

That doesn't happen with printf, so it's less common to check the return.

If you need to change your behaviour based on whether a function worked, you check the return. Many standard library functions either can fail, or will cause undefined behaviour later, so you need to check those returns.

If you don't need to change the behaviour based on the return value, then there's no point checking it.

Pete Kirkham
+1  A: 

If the function may return error code - always check it and handle it, as simple as this. This rule can save you a lot of time during bug hunting.

If function always returns the code that cannot indicate the error and you don't need the result (like printf) of course you can ignore it.

qrdl
This approach is the difference between a program that just crashes and a program that exits as gracefully as possible with error logs indicating what went wrong.
Harvey
Nope. Not all errors in standard functions cause crashes, and you will spend long hours looking for problem origin. Been there, done that. Didn't like it.
qrdl
+2  A: 

It took me a long time to learn this, but barring few exceptions you should always check the return code of a function.

I've seen far too much code that calls malloc (for example) and just happily uses the pointer it returns. 99.9% of the time, this isn't a problem, but occasionally malloc will fail and your program will crash when you try to dereference a NULL pointer. Now, one might argue that you want to exit if malloc returns NULL anyway -- and that may be true, but you should always strive to exit gracefully, even on a fatal error.

So, yes: check return codes. Don't assume something works just because it always worked in the past. Things fail all the time. You'll save yourself lots of time and grief by coding defensively, checking for errors, checking errno, outputting strerror and failing gracefully.

FreeMemory
+1  A: 

If the function returns an error code, your calling code should decide how to handle an error. For some programs, ignoring the error may be OK; this tends to be what people do with errors from the standard I/O library when writing to stderr, for example. (What can you do if the message failed? Exit? Are you doing that anyway?)

One source of nuisance are functions that are documented to return a value but always return the same value (typically 0). Often, these are functions originally written in K&R C before there was a void return. They were converted to int and then had a 'return(0);' added to quell warnings about 'function does not return a value', rather than converting it to void as it should have been. Such functions should be revised to void; in the interim, it is OK to ignore their error return value.

I disagree with the observation in another answer "capture return/error codes when you expect problems with the function call". The problem is precisely the unexpected is what kills you. Even the most stable of operations can fail unexpectedly (maybe the DBMS has crashed, so even though you had a connection, you don't any more), and your software has to recognize and deal with such issues.

Jonathan Leffler
+1  A: 

Yes, with very few exceptions your program should always check for and handle error return values, even (especially) if you do not expect any errors. The environment of our software is often less reliable than we would wish, after all.

Incidentially, this is why most modern languages have exceptions: among other things, they provide a "default error handler" (abort and stack trace) for errors you do not handle (i.e. catch) explicitly. They also allow centralising error handling, instead of checking the return value of every function call.

sleske