编写高质量C语言代码--assert yourself

来源:互联网 发布:2017日本就业率数据 编辑:程序博客网 时间:2024/05/01 13:40


        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 DEBUGif(pvTo == NULL || pvFrom == NULL){fprintf(stderr, "Bad args in memcpy\n");abort();}#endifwhile(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您的程序!