當(dāng)前位置:
首頁 >
C++ 自定义调试信息的输出
發(fā)布時(shí)間:2023/12/4
35
豆豆
生活随笔
收集整理的這篇文章主要介紹了
C++ 自定义调试信息的输出
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
自定義調(diào)試信息的輸出 調(diào)試信息的輸出方法有很多種,? 例如直接用printf,? 或者出錯(cuò)時(shí)使用perror, fprintf等將信息直接打印到終端上, 在Qt上面一般使用qDebug,而守護(hù)進(jìn)程則一般是使用syslog將調(diào)試信息輸出到日志文件中等等... 使用標(biāo)準(zhǔn)的方法打印調(diào)試信息有時(shí)候不是很方便,? 例如Qt編程, 在調(diào)試已有的代碼時(shí), 我想在打印調(diào)試信息的地方, 把代碼位置也打印出來以方便定位錯(cuò)誤, 或者需要在調(diào)試信息前面加一個(gè)前輟, 好方便在調(diào)試信息太多的時(shí)候可以用grep過濾一下, 僅顯示本模塊的調(diào)試信息, 這時(shí)就需要一個(gè)一個(gè)地修改已有的qDebug, 使其成為以下形式:
qDebug( "[模塊名稱] 調(diào)試信息? File:%s, Line:%d", __FILE__, __LINE__ );
這樣的修改比較煩人, 而且一不小心會(huì)遺漏某個(gè)沒改的... 為了能方便地管理調(diào)試信息的輸出,一個(gè)比較簡單的方法就是自已定義一個(gè)打印調(diào)試信息的宏, 然后替換原來的,廢話就不多說了,直接給出一個(gè)現(xiàn)成的,下面是一個(gè)例子, 我用WiFi表示當(dāng)前代碼的模塊名稱,我要求在模塊中的所有調(diào)試信息前面均帶有[WiFi]前輟,這樣我就能方便地只需使用命令行 | grep "\[WiFi\]"來過濾掉來自其它模塊的調(diào)試信息了: #define qWiFiDebug(format, ...) qDebug("[WiFi] "format" File:%s, Line:%d, Function:%s", ##__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__); 上面的宏是使用qDebug輸出調(diào)試信息,在非Qt的程序中也可以改為printf,守護(hù)進(jìn)程則可以改為syslog等等...? 其中,決竅其實(shí)就是這幾個(gè)宏 ##__VA_ARGS__, __FILE__, __LINE__ 和__FUNCTION__,下面介紹一下這幾個(gè)宏: 1)? __VA_ARGS__ 是一個(gè)可變參數(shù)的宏,很少人知道這個(gè)宏,這個(gè)可變參數(shù)的宏是新的C99規(guī)范中新增的,目前似乎只有g(shù)cc支持(VC6.0的編譯器不支持)。宏前面加上##的作用在于,當(dāng)可變參數(shù)的個(gè)數(shù)為0時(shí),這里的##起到把前面多余的","去掉的作用,否則會(huì)編譯出錯(cuò), 你可以試試。
2) __FILE__ 宏在預(yù)編譯時(shí)會(huì)替換成當(dāng)前的源文件名
3) __LINE__宏在預(yù)編譯時(shí)會(huì)替換成當(dāng)前的行號
4) __FUNCTION__宏在預(yù)編譯時(shí)會(huì)替換成當(dāng)前的函數(shù)名稱 有了以上這幾個(gè)宏,特別是有了__VA_ARGS__ ,調(diào)試信息的輸出就變得靈活多了。
有時(shí),我們想把調(diào)試信息輸出到屏幕上,而有時(shí)則又想把它輸出到一個(gè)文件中,可參考下面的例子: //debug.c #include <stdio.h>
#include <string.h> //開啟下面的宏表示程序運(yùn)行在調(diào)試版本, 否則為發(fā)行版本, 這里假設(shè)只有調(diào)試版本才輸出調(diào)試信息
#define _DEBUG #ifdef _DEBUG
??? //開啟下面的宏就把調(diào)試信息輸出到文件,注釋即輸出到終端
??? #define DEBUG_TO_FILE
??? #ifdef DEBUG_TO_FILE
??????? //調(diào)試信息輸出到以下文件
??????? #define DEBUG_FILE "/tmp/debugmsg"
??????? //調(diào)試信息的緩沖長度
??????? #define DEBUG_BUFFER_MAX 4096
??????? //將調(diào)試信息輸出到文件中
??????? #define printDebugMsg(moduleName, format, ...) {\
??????????? char buffer[DEBUG_BUFFER_MAX+1]={0};\
??????????? snprintf( buffer, DEBUG_BUFFER_MAX \
??????????????????? , "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );\
??????????? FILE* fd = fopen(DEBUG_FILE, "a");\
??????????? if ( fd != NULL ) {\
??????????????? fwrite( buffer, strlen(buffer), 1, fd );\
??????????????? fflush( fd );\
??????????????? fclose( fd );\
??????????? }\
??????? }
??? #else
??????? //將調(diào)試信息輸出到終端
??????? #define printDebugMsg(moduleName, format, ...) \
????????????????? printf( "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );
??? #endif //end for #ifdef DEBUG_TO_FILE
#else
??? //發(fā)行版本,什么也不做
??? #define printDebugMsg(moduleName, format, ...)
#endif? //end for #ifdef _DEBUG int main(int argc, char** argv)
{
??? int data = 999;
??? printDebugMsg( "TestProgram", "data = %d", data );
??? return 0;
}
? 上面也說了,只有支持C99規(guī)范的gcc編譯器才有__VA_ARGS__這個(gè)宏,如果不是gcc編譯器,或者所用的gcc編譯器版本不支持__VA_ARGS__宏怎么辦? 可參考下面的代碼片段,我們換一種做法,可先將可變參數(shù)轉(zhuǎn)換成字符串后,再進(jìn)行輸出即可: void printDebugMsg( const char* format, ...)
{
??? char buffer[DEBUG_BUFFER_MAX_LENGTH + 1]={0}; va_list arg;
??? va_start (arg, format);
??? vsnprintf(buffer, DEBUG_BUFFER_MAX_LENGTH, format, arg);
??? va_end (arg); printf( "%s", buffer );
}
? ?
qDebug( "[模塊名稱] 調(diào)試信息? File:%s, Line:%d", __FILE__, __LINE__ );
這樣的修改比較煩人, 而且一不小心會(huì)遺漏某個(gè)沒改的... 為了能方便地管理調(diào)試信息的輸出,一個(gè)比較簡單的方法就是自已定義一個(gè)打印調(diào)試信息的宏, 然后替換原來的,廢話就不多說了,直接給出一個(gè)現(xiàn)成的,下面是一個(gè)例子, 我用WiFi表示當(dāng)前代碼的模塊名稱,我要求在模塊中的所有調(diào)試信息前面均帶有[WiFi]前輟,這樣我就能方便地只需使用命令行 | grep "\[WiFi\]"來過濾掉來自其它模塊的調(diào)試信息了: #define qWiFiDebug(format, ...) qDebug("[WiFi] "format" File:%s, Line:%d, Function:%s", ##__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__); 上面的宏是使用qDebug輸出調(diào)試信息,在非Qt的程序中也可以改為printf,守護(hù)進(jìn)程則可以改為syslog等等...? 其中,決竅其實(shí)就是這幾個(gè)宏 ##__VA_ARGS__, __FILE__, __LINE__ 和__FUNCTION__,下面介紹一下這幾個(gè)宏: 1)? __VA_ARGS__ 是一個(gè)可變參數(shù)的宏,很少人知道這個(gè)宏,這個(gè)可變參數(shù)的宏是新的C99規(guī)范中新增的,目前似乎只有g(shù)cc支持(VC6.0的編譯器不支持)。宏前面加上##的作用在于,當(dāng)可變參數(shù)的個(gè)數(shù)為0時(shí),這里的##起到把前面多余的","去掉的作用,否則會(huì)編譯出錯(cuò), 你可以試試。
2) __FILE__ 宏在預(yù)編譯時(shí)會(huì)替換成當(dāng)前的源文件名
3) __LINE__宏在預(yù)編譯時(shí)會(huì)替換成當(dāng)前的行號
4) __FUNCTION__宏在預(yù)編譯時(shí)會(huì)替換成當(dāng)前的函數(shù)名稱 有了以上這幾個(gè)宏,特別是有了__VA_ARGS__ ,調(diào)試信息的輸出就變得靈活多了。
有時(shí),我們想把調(diào)試信息輸出到屏幕上,而有時(shí)則又想把它輸出到一個(gè)文件中,可參考下面的例子: //debug.c #include <stdio.h>
#include <string.h> //開啟下面的宏表示程序運(yùn)行在調(diào)試版本, 否則為發(fā)行版本, 這里假設(shè)只有調(diào)試版本才輸出調(diào)試信息
#define _DEBUG #ifdef _DEBUG
??? //開啟下面的宏就把調(diào)試信息輸出到文件,注釋即輸出到終端
??? #define DEBUG_TO_FILE
??? #ifdef DEBUG_TO_FILE
??????? //調(diào)試信息輸出到以下文件
??????? #define DEBUG_FILE "/tmp/debugmsg"
??????? //調(diào)試信息的緩沖長度
??????? #define DEBUG_BUFFER_MAX 4096
??????? //將調(diào)試信息輸出到文件中
??????? #define printDebugMsg(moduleName, format, ...) {\
??????????? char buffer[DEBUG_BUFFER_MAX+1]={0};\
??????????? snprintf( buffer, DEBUG_BUFFER_MAX \
??????????????????? , "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );\
??????????? FILE* fd = fopen(DEBUG_FILE, "a");\
??????????? if ( fd != NULL ) {\
??????????????? fwrite( buffer, strlen(buffer), 1, fd );\
??????????????? fflush( fd );\
??????????????? fclose( fd );\
??????????? }\
??????? }
??? #else
??????? //將調(diào)試信息輸出到終端
??????? #define printDebugMsg(moduleName, format, ...) \
????????????????? printf( "[%s] "format" File:%s, Line:%d\n", moduleName, ##__VA_ARGS__, __FILE__, __LINE__ );
??? #endif //end for #ifdef DEBUG_TO_FILE
#else
??? //發(fā)行版本,什么也不做
??? #define printDebugMsg(moduleName, format, ...)
#endif? //end for #ifdef _DEBUG int main(int argc, char** argv)
{
??? int data = 999;
??? printDebugMsg( "TestProgram", "data = %d", data );
??? return 0;
}
? 上面也說了,只有支持C99規(guī)范的gcc編譯器才有__VA_ARGS__這個(gè)宏,如果不是gcc編譯器,或者所用的gcc編譯器版本不支持__VA_ARGS__宏怎么辦? 可參考下面的代碼片段,我們換一種做法,可先將可變參數(shù)轉(zhuǎn)換成字符串后,再進(jìn)行輸出即可: void printDebugMsg( const char* format, ...)
{
??? char buffer[DEBUG_BUFFER_MAX_LENGTH + 1]={0}; va_list arg;
??? va_start (arg, format);
??? vsnprintf(buffer, DEBUG_BUFFER_MAX_LENGTH, format, arg);
??? va_end (arg); printf( "%s", buffer );
}
? ?
轉(zhuǎn)載于:https://blog.51cto.com/laokaddk/214225
總結(jié)
以上是生活随笔為你收集整理的C++ 自定义调试信息的输出的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从Banner入手保护linux系统服务
- 下一篇: VC++的dll中接收消息