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)。一旦断言失败,会引发一个异常。