C语言中assert功能强大,人称“断言”,如语句assert ( expression ),即断言expression始终为true, 若为false,则程序运行失败。
但是,assert ( expression ) 看似function,但它其实是macro, 而且只是一个debug-only的宏,即只有在定义DEBUG宏的情况下才有用。但是它却是一个强大的高度工具,而且也是编码bug-free的code的有力助手。
举个例子,有以下这样一个function:
example 1:
/* memcpy -- copy a nonoverlapping memory block */
void* memcpy(void* pvTo, void* pvFrom, size_t size)
{
byte* pbTo = (byte*)pvTo;
byte* pbFrom = (byte*)pvFrom;
while(size-- > 0)
*pbTo = *pvFrom;
return(pvTo);
}
有经验的programmer一看就知道这是一个有bug的function。如果如此应用:
1.
memcpy(NULL, pvFrom, size);
2.
memcpy(pvTo, NULL, size);
就会出现问题。NULL是0,而对0地址解引用会出现什么事?SO BAD!
那么怎么办呢?在对pbTo与pvFrom解引用之前进行指针检查,进行如下改变:
example 2 :
/* memcpy -- copy a nonoverlapping memory block */
void* memcpy(void* pvTo, void* pvFrom, size_t size)
{
byte* pbTo = (byte*)pvTo;
byte* pbFrom = (byte*)pvFrom;
if(pvTo == NULL || pvFrom == NULL){
fprintf(stderr, "Bad args in memcpy\n");
abort();
}
while(size-- > 0)
*pbTo = *pvFrom;
return(pvTo);
}
OK, Perfect !但是身为一个持有完美主义的coder,似乎这样的代码不是那么一回事。有人教导我们,编写代码的时候要有两个版本:Debug Version and Ship Version。我们新加的语句好像是Debug Version里的吧,怎么能让它出现在Ship Version里呢?于是乎:
example 3:
/* memcpy -- copy a nonoverlapping memory block */
void* memcpy(void* pvTo, void* pvFrom, size_t size)
{
byte* pbTo = (byte*)pvTo;
byte* pbFrom = (byte*)pvFrom;
#ifdef DEBUG
if(pvTo == NULL || pvFrom == NULL){
fprintf(stderr, "Bad args in memcpy\n");
abort();
}
#endif
while(size-- > 0)
*pbTo = *pvFrom;
return(pvTo);
}
这下没问题了吧?嗯,我们的主角assert呢?怎么没有?别急,马上就来,有句话不是说:英雄总是最后登场的嘛。注意我们加的Debug语句不就是在测试pvTo与pvFrom不为NULL吗?这不就是assert的功能!So:
example 4:
/* memcpy -- copy a nonoverlapping memory block */
void* memcpy(void* pvTo, void* pvFrom, size_t size)
{
byte* pbTo = (byte*)pvTo;
byte* pbFrom = (byte*)pvFrom;
assert(pvTo != NULL && pvFrom != NULL);
while(size-- > 0)
*pbTo = *pvFrom;
return(pvTo);
}
嗯,好像可以了。但是~,如果pvTo与pvFrom指向的内存块是overlapped的呢?oh, no!所以还等断言pvTo与pvFrom是没有overlapped的。最终版登场:
example5:
/* memcpy -- copy a nonoverlapping memory block */
void* memcpy(void* pvTo, void* pvFrom, size_t size)
{
byte* pbTo = (byte*)pvTo;
byte* pbFrom = (byte*)pvFrom;
assert(pvTo != NULL && pvFrom != NULL);
assert(pvTo >= pvFrom + size || pvFrom >= pbTo + size);
while(size-- > 0)
*pbTo = *pvFrom;
return(pvTo);
}
小结:请使用assert 来code您的程序!