使用工具:VC6.0,IDA
當我們要在程序中輸出調試信息時,常常以字符串的形式來輸出,例如:
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,雖然該函數什麼都不做,
但它卻調用了,我們一般也不希望該函數調用,所以方法一中多了一個函數調用,增加了開銷,
而方法二當中卻沒有調用該函數。
個人認為方法二較好。
結束語:
若要轉載該文章,請保持原文章的完整性,謝謝!
本文配套源碼