????????DDK提供了大量的宏。在使用這些宏的時候,要注意一種錯誤的發生,這就是“側效”(Side Effect)。
????????宏一般由多行組成,如下面的形式,其中“\”代表換行。
#define PRINT(msg) KdPrint(("===============\n")); \KdPrint(msg);?? ?\KdPrint(("===============\n"));
?? ??? ?
????????在C語言中規定,for或者if語句塊中的內容如果只是一句,可以省略掉{}。如:
if(ret)
{Foo();
}
????????等價于
if(ret)Foo();
????????但如果Foo是宏而非函數時,就會產生邏輯錯誤。
if(bRet)PRINT(msg);
等價于
if(bRet) KdPrint(("===============\n")); \KdPrint(msg);?? ?\KdPrint(("===============\n"));
????????這明顯和我們開始的想法不一致。產生這樣的錯誤,稱為“側效”錯誤。“側效”錯誤很難被發現,因為程序員很難判斷Foo是函數還是宏。
????????解決這個問題,一般有兩個辦法。
????????1. 對于if、while、for這樣的語句,不省略{}。這樣是最保險的做法,能完全保證不出現“側效”錯誤。
????????2. 在編寫多行宏的時候,在宏的前后加上{}。如下面的形式,其中“\”代表換行。
#define PRINT(msg) {KdPrint(("===============\n")); \
?? ??? ?KdPrint(msg);?? ?\
?? ??? ?KdPrint(("===============\n")); \
?? ??? ?}
這種方法能保證這個宏在調用時,不出現“側效”錯誤。
斷言
????????在驅動程序開發中,還有一個技巧,就是使用“斷言”。在驅動程序使用“斷言”,一般是通過使用ASSERT宏。例如:
NTSTATUS Foo(PCHAR* str)
{
?? ?ASSERT(str!=NULL);// 斷言
?? ?
?? ?// 對str的操作
}
????????這段代碼認為輸入參數絕不可能是空指針,因此在函數的開頭做一個斷言(ASSERT)。一旦斷言失敗,會引發一個異常。