2009-11-05 7 views
3

Мне просто интересно, что является лучшим способом создания пользовательских функций ошибки печати.Сообщения об ошибках печати

Например, у меня есть некоторые #defines, как это в файле заголовка:

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

Тогда, возможно, используя это так:

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

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

Однако, я не думаю, что это идеальный и хотите сделать что-то намного лучше. Может быть, что-то более профессиональное и, возможно, более масштабируемое.

Большое спасибо за любые советы,

+1

Используйте 'fprintf (stderr, ...)', чтобы сообщать об ошибках (или, по крайней мере, нормально писать в 'stderr', а не 'stdout' - или записывать в файл журнала или оба файла журнала и stderr). –

ответ

3

Вы могли бы рассмотреть возможность использования variadic functions для сообщений об ошибках, они становятся намного более универсальны.

Например

#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); 
} 

Какой может быть вызван как (обратите внимание, я предполагаю, что есть C99 компилятор):

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

Это может легко связать с другими ответами предполагая, что коды ошибок могут быть определены в перечислимых списках с постоянным массивом строк для их перевода. Я оставлю это как упражнение для читателя. Очень просто сделать пример выше, принять больше аргументов.

NB: Если вы используете что-то вроде буфера символов [LEN] для пользовательского форматирования печатной строки, измените ее с void на unsigned int, верните количество байтов, которое vsnprintf() не может распечатать, что может быть полезно вызывающему абоненту. Вышеприведенный пример является «безопасным», в котором вам не нужно беспокоиться о перетекании некоторого стекового распределенного буфера с отформатированным сообщением об ошибке неопределенной длины. Или оставьте его как пустоту и распечатайте, что он может (хотя он не может распечатать все), вплоть до вас. Обратный подход к этому подходу не совсем знает длину вариационных аргументов после расширения. В конце концов, вы сообщаете о неожиданных результатах :)

Этот подход позволяет вам больше помочь, передавая содержательные и информативные сообщения об ошибках, а также просто записывая их в любой открытый файл.

Я знаю, что этот пример в основном описывает printf(). Я отправляю его, чтобы показать, насколько легко адаптироваться и расширяться.

+0

Здравствуйте. Я думаю, это звучит как лучшая идея. Знаете ли вы какие-либо ссылки, где это было использовано? – ant2009

+0

Имя C99 для функции - '' __func__' ', а не '' __FUNCTION__''. –

+0

@ Джонатан Леффлер: Да, вы правы. Я слишком привык к тому, чтобы успокаивать существ. –

3

ЗАКАНЧИВАТЬ log4c некоторые идеи, как реализовать протоколирование.

Вот несколько советов: не печатайте «была ошибка». Предоставьте как можно больше информации: Какой IP-адрес? Код ошибки? Чего добился ваш код?

Когда вам нужно написать сообщение об ошибке, задайте себе этот вопрос: что мне нужно знать, когда я вижу это сообщение об ошибке? Что мне поможет исправить вопрос?

+2

Добавить в вопрос: кто является сообщением об ошибке (например, разработчик, пользователь)?Какая информация полезна, зависит от аудитории. Ниже приводятся ошибки GUI, но содержат полезную информацию для сообщений об ошибках в целом: 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

Вы также можете сделать что-то вроде этого:

//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]); 
    } 
} 
+3

Большинство систем резервируют 0 для 'не ошибки'. В C99 вы можете использовать назначенные инициализаторы, такие как: '[SOCKET_ERR] =" Socket failure ", что значительно повышает надежность инициализатора для errorDesc. –

Смежные вопросы