2017-06-21 47 views
0

雖然我在做C編程,但我想打印出一些特殊情況的警告,以使程序更加健壯。不過,我平時遇見喜歡的情況:我應該向stderr打印警告信息的級別是多少?

float a(...) { 
    float *p = NULL; 
    if (p == NULL) fprintf(stderr, "err_lvl_2"); 
    ...; 
} 

float *b(...) { 
    float *p; 
    ...; 
    p = Cal(...); 
    if (p == NULL) fprintf(stderr, "err_lvl_1"); 
    ... 
    return p; 
} 

警告信息err_lvl_1err_lvl_2幾乎是一樣的嗎?我認爲這有點煩人。如果使用更高級別的嵌套,會更糟糕。但我不知道我應該在哪個級別進行最好的打印。

+0

有一個打印出多年來長大的「堆棧跟蹤」的約定。雖然在C中並不那麼微不足道。 – Bathsheba

+2

'err_lvl_1'和'err_lvl_2'不是警告信息級別。我想你需要實現你的自定義日誌級別打印功能。 – Gaurav

+0

您可能想要以此風格創建*完整的工作程序*,並在[codereview.se]中發佈。首先,請閱讀[Stack Overflow用戶的代碼評論指南](// codereview.meta.stackexchange.com/a/5778),因爲有些事情在那裏以不同的方式完成! –

回答

1

實際上,這些消息不是很豐富。你想能夠發現哪裏出了點問題–和什麼。因此,你根本不需要錯誤級別。想象一下,你在控制檯上看到「err_lvl_1」,但你用它在你的應用程序有許多不同的位置...

你最好讓更多的具體信息,如:

fprintf(stderr, "(%4u) %s: p == NULL\n", __LINE__, __func__); 

你可以把這個成宏,這樣你得到統一的日誌記錄:

#define LOG(FORMAT, ...) \ 
    fprintf(stderr, "(%4u) %s: " FORMAT "\n", __LINE__, __func__, ## __VA_ARGS__); 

LOG("value of x was %d", x); 

(請注意,上面##是一個GCC擴展沒有可變參數,那麼這將跳過逗號–其他編譯器可能requir的情況下Ë不同的解決方案...)

當然,你可以選擇更多的神祕字眼,試圖掩蓋內部用戶,只要你迅速從你需要得到什麼......

水平,如果有的話,通常用於切換更詳細的日誌記錄(或關閉),無論是在編譯時,或當你的程序運行(或兩者相結合,比如下圖):

#define LEVEL_NONE 0 
#define LEVEL_FATAL 1 
#define LEVEL_ERROR 2 
// WARNING, INFO, DEBUG, TRACE, ... 

#if STATIC_LOG_LEVEL < LEVEL_ERROR 
#define LOG_ERROR(FORMAT, ...) 
#else 
#define LOG_ERROR(FORMAT, ...)    \ 
    do          \ 
    {          \ 
     if(currentLevel >= LEVEL_ERROR)  \ 
      fprintf(stderr, "(%4u) %s: " FORMAT "\n", __LINE__, __func__, ## __VA_ARGS__) \ 
    }          \ 
    while(0) 
#endif 

除了打印到標準錯誤,你可能會打印到一個文件代替–等等,你剛剛開始了一些最小化的記錄系統......你不需要從一開始就發明它,但是,已經有足夠的,例如log4c,例如(不要問我它是否好,但–嘗試,如果你不喜歡它,尋找另一個... –或如果你喜歡,繼續我上面開始的)。

爲什麼要切換關卡?那麼,只要一切運行良好,您可能希望減少日誌記錄(以獲得更好的性能,更小的日誌文件...),但是在開發/測試應用程序時或者在稍後發生錯誤的情況下,您可能需要有更詳細的日誌記錄來跟蹤錯誤...