2009-11-05 196 views
3

我只是想知道什麼是使自定義打印錯誤功能的最佳途徑。打印錯誤消息

例如,我有一些#define語句像這樣的頭文件:

#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中(錯誤,...)」報告錯誤(或者,至少,通常寫爲「標準錯誤」,而不是「標準輸出」 - 或寫入日誌文件,或兩者日誌文件和標準錯誤)。 – 2009-11-05 08:51:52

回答

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__); 

這很容易配合其他答案提示錯誤代碼可以在枚舉列表中定義,並使用常量字符串來轉換它們。我將把它作爲讀者的練習。上面的例子很容易讓人接受更多的論據。

注意:如果使用類似char buffer [LEN]的格式來打印字符串,請將其從void更改爲unsigned int,讓它返回vsnprintf()無法打印的字節數,這可能有用給來電者。上面的例子是'安全的',其中你不必擔心流過一些堆棧分配的緩衝區,其格式錯誤消息的長度未定義。或者,將其視爲無效並將其打印出來(注意它無法打印所有內容),由您決定。這種方法的缺點並不完全知道一旦擴展了可變參數的長度。畢竟,你要回報意想不到的結果:)

這種方法可以讓你幫助自己更多的輸送有意義的信息的錯誤信息,以及簡單地將其記錄到任何打開的文件。

我知道,這個例子主要描述的printf()本身。我發佈它來展示適應和擴展是多麼容易。

+0

你好。我認爲這聽起來像是最好的主意。你知道這些已被使用的任何鏈接嗎? – ant2009 2009-11-05 11:03:08

+0

函數的C99名稱是「__func__」,而不是「__FUNCTION__」。 – 2009-11-05 13:28:36

+0

@Jonathan Leffler:是的,你是對的。我太習慣glibc生物的舒適。 – 2009-11-05 14:25:06

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 2009-11-05 08:48:34

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] =「套接字故障」,這極大地提高了errorDesc初始化程序的可靠性。 – 2009-11-05 08:50:58