1. 程式人生 > >輸出資訊到DEBUGVIEW視窗

輸出資訊到DEBUGVIEW視窗

TRACE巨集對於VC下程式除錯來說是很有用的東西,有著類似printf的功能;該巨集僅僅在程式的DEBUG版本中出現,當RELEASE的時候該巨集就完全訊息了,從而幫助你調式也在RELEASE的時候減少程式碼量。

使用非常簡單,格式如下:

TRACE("DDDDDDDDDDD");

TRACE("wewe%d",333);

同樣還存在TRACE0,TRACE1,TRACE2。。。分別對應0,1,2。。個引數

TRACE資訊輸出到VC IDE環境的輸出視窗(該視窗是你編譯專案出錯提示的哪個視窗),但僅限於你在VC中執行你的DEBUG版本的程式。

TRACE資訊還可以使用DEBUGVIEW來捕獲到。這種情況下,你不能在VC的IDE環境中執行你的程式,而將BUILD好的DEBUG版本的程式單獨執行,這個時候可以在DEBUGVIEW的視窗看到DEBUGVIE格式的輸出了。

------------------第二種方法------------------------------

OutputDebugString is a API function, it is used to help programmer debug the program, which is like 
TRACE or afxDump, it is work with Dbgview. in Debug mode it performance as TRACE. But in Release mode
it can be monitor in DbgView.


OutputDebugString is explained in MSDN

The OutputDebugString function sends a string to the debugger for the current application. 

VOID OutputDebugString(
  LPCTSTR lpOutputString
   // pointer to string to be displayed
);
 
Parameters:

lpOutputString parameters Pointer to the null-terminated string to be displayed. 

Return Values
This function does not return a value. 

Remarks
If the application has no debugger, the system debugger displays the string. 
If the application has no debugger and the system debugger is not active, 
OutputDebugString does nothing. 


Example:


void CSdfghfgView::OnRButtonDown(UINT nFlags, CPoint point) 
{
 // TODO: Add your message handler code here and/or call default
 OutputDebugString("right button is pressed");
}

 引數就是你需要輸出的字串了。如果你需要顯示數字等,你需要事先格式化字串。注意WINDOWS CE僅僅支援UNICODE版本,所以你提供的字串應該轉換為UNICODE。使用_tstrcat等來格式化字串。

如果你的應用程式有一個DEBUGER,那麼該函式輸出到DEBUGER,否則就輸出到系統的DEBUGER,如果兩個都沒有,該函式什麼也不做。

注意,輸出到系統DEBUGER的,你可以使用DEBUGVIEW工具檢視日誌,這樣你在程式執行的時候也可以看到日誌了。很多程式都使用這種方式來寫日誌,包括MICROSOFT本身也使用這種方法。

------------------第三種輸出方法------------------------------------

當我們要在程式中輸出除錯資訊時,常常以字串的形式來輸出,例如:

      printf("Some debug information here!/n");

這段程式碼在Debug和Release版下都輸出除錯資訊,這不是我們所要的,一般地大家都會新增
預編譯指令,如下所示:

#if _DEBUG  

printf("Some debug information here!/n");       

#endif

這樣就達到了在Debug版里程序輸出除錯資訊,在Release版下不輸出除錯資訊的目的。(在Release版裡
連printf函式都沒有呼叫)可如果要在程式裡的許多地方輸出除錯資訊,若採用上面的方式會很麻煩;
(至於為什麼麻煩,可能就是不願多敲幾次鍵盤吧,呵呵。。。)

於是大家都想到寫個輸出函式,程式碼如下:

 void printInfo(char *strInfo)       
 {     
 #if _DEBUG             
 printf(strInfo);     
 #endif     
 }
注:該函式只是演示用的,很簡單,沒有其他檢查字串功能。

在要輸出除錯資訊的地方,呼叫如下語句就行:
      printInfo("Some debug information here!/n");      
確實,在Debug模式下執行該程式,則輸出如下資訊:
      Some debug information here!

在Release模式下,則沒輸出什麼資訊;

我們往往在這個時候認為一切都OK了;如果你認為是,就沒必要往下看了;呵呵。。。

雖然在Release版下執行程式沒有輸出除錯資訊來,可這些除錯資訊卻留在了二進位制的可執行檔案裡;
我們可以用IDA來開啟該Release版的可執行檔案,看到如圖一所示的資訊:

 
                                            圖一:IDA反彙編後的main函式


注:該函式就是main函式

可見除錯資訊字串(“Some debug information here!/n”)確實存在於Release版的可執行檔案裡; 
我們當然不希望別人看到這些除錯資訊,那有沒有辦法來防止該除錯資訊被編譯進Release版的可執行檔案裡呢?
辦法是有的,這裡來描述2個方法。

辦法一:
定義如下巨集:

#if _DEBUG       

#define _D(str) str       

#else      

#define _D(str) NULL         

#endif

此時輸出語句變為:
      printInfo(_D("Some debug information here!/n"));          
在Debug模式下執行程式,依然輸出除錯資訊:
“Some debug information here!”;
在Release下,則什麼都不輸出,此時我們用IDA看一下Release版的二進位制檔案,則沒有發現該除錯資訊字串。
如圖二示:


                                                     圖二:IDA反彙編後的main函式

方法二:
定義如下巨集:
#if _DEBUG    
void printInfo(char *strInfo)    
{       
printf(strInfo);     
}      
#else   
#define printInfo(str)      
#endif
注意:該巨集把函式printInfo的定義也放進去了; 
在Debug模式下執行程式,也同樣輸出除錯資訊:
“Some debug information here!”;

在Release下,也什麼都不輸出,此時我們用IDA看一下Release版的二進位制檔案,也沒有發現該除錯資訊字串。

如圖三示:

 
                                           圖三:IDA反彙編後的main函式

既然方法一和方法二都能實現同樣的功能,那究竟那個方法好呢?

方法一和方法二確實都沒在可執行檔案裡留下除錯資訊,比較一下圖二和圖三,我們不難發現:
圖二當中多了一個函式呼叫 call nullsub_1,該函式就是printInfo,雖然該函式什麼都不做,
但它卻呼叫了,我們一般也不希望該函式呼叫,所以方法一中多了一個函式呼叫,增加了開銷,
而方法二當中卻沒有呼叫該函式。

下面是程式原始碼:

// 程式目的:
// 測試除錯時輸出的字串資訊

#include <stdio.h>

//#define Method
#ifdef Method

//方法一
void printInfo(char *strInfo)
{
#if _DEBUG
    printf(strInfo);
#endif
}

#if _DEBUG
#define _D(str) str
#else
#define _D(str) NULL
#endif
int main()
{
 printInfo(_D("Some debug information here!/n"));
 return 0;
}

#else

//方法二
#if _DEBUG
void printInfo(char *strInfo)
{
    printf(strInfo);
}
#else
#define printInfo(str)
#endif

int main()
{
 printInfo("Some debug information here!/n");
 return 0;
}

#endif