tags:

views:

102

answers:

3

Hello,

I am just wondering what is the best way to make custom print error functions.

For example I have some #defines like this in header file:

#define SOCKET_ERR 0
#define BIND_ERR   1
#define LISTEN_ERR 2 
etc

Then maybe using this like this:

if(/*something has gone wrong with socket*/)
{
   print_error(SOCKET_ERR);
}

print_error(int error)
{
   if(error == 0)
   {
       printf("Socket failure\n");
   }
}

However, I don't think this perfect and want to do something much better. Maybe something a little bit more professional and maybe more scalable.

Many thanks for any advice,

+2  A: 

Check out log4c for some ideas how to implement logging.

Here is some advice: Don't just print "there was an error". Give as much information as possible: Which IP address? Error-Code? What did your code try to achieve?

When you need to write an error message, ask yourself this question: What will I need to know when I see this error message? What will help me to fix the issue?

Aaron Digulla
Add to questions: who is the error message for (e.g. developer, user)? What information is helpful depends on the audience. The following are for GUI errors, but contain useful info for error messages in general: http://developer.apple.com/mac/library/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGWindows/XHIGWindows.html#//apple_ref/doc/uid/20000961-TPXREF23 http://msdn.microsoft.com/en-us/library/ms995351.aspx
outis
+2  A: 

You can also do something like this:

//Enum for the error codes
typedef enum
{
    SOCKET_ERR = 0,
    BIND_ERR,
    LISTEN_ERR,
    LAST_ENTRY //This SHOULD be the last entry
} ErrorCode;

//Error descriptions..number of entries should match the number of entries in Enum
const char* errorDesc[] =
{
    "Socket failure",
    "Bind failure",
    "Listen failure",
    "Dummy"
};


void printError(ErrorCode c)
{
    //Validate..
    if( c < LAST_ENTRY)
    {
     printf(errorDesc[c]);
    }
}
Naveen
Most systems reserve 0 for 'not an error'. In C99, you can use designated initializers like: `[SOCKET_ERR] = "Socket failure",` which dramatically improves the reliability of the initializer for errorDesc.
Jonathan Leffler
+2  A: 

You might consider using variadic functions for error reporting, they become so much more versatile.

For instance

#include <stdarg.h>
void my_error(FILE *out, const char *fmt, ...)
{
    va_list ap;
    va_start(ap_fmt);
    vfprintf(out, fmt, ap);
    va_end(ap);
}

Which could be invoked like this (note, I'm assuming a c99 compiler):

my_error(stderr,
    "%s: Invalid range of %ld near line %d", __func__, range, __LINE__);

This could easily tie in with other answers suggesting that error codes could be defined in enumerated lists, with a constant array of strings to translate them. I'll leave that as an exercise for the reader. Its very easy to make the example above accept more arguments.

NB: If you use something like char buffer[LEN] to custom format the printed string, change it from void to unsigned int, have it return the number of bytes that vsnprintf() could not print, that might be useful to the caller. The above example is 'safe', wherein you don't have to worry about over flowing some stack allocated buffer with a formatted error message of undefined length. Or, leave it as void and have it print what it can (while noting it could not print everything), up to you. The draw back to this approach is not quite knowing the length of the variadic arguments once expanded. After all, you're reporting unexpected results :)

This approach lets you help yourself more by conveying meaningful and informative error messages, as well as simply logging them to any open file.

I know that this example basically describes printf() itself. I'm posting it to show how easy it is to adapt and expand.

Tim Post
Hello. I think that sounds like the best idea. Do you know of any links where this has been used?
robUK
The C99 name for the function is '`__func__`' and not '`__FUNCTION__`'.
Jonathan Leffler
@Jonathan Leffler: Yes, you are right. I'm getting too used to glibc creature comforts.
Tim Post