引言
- https://blog.csdn.net/qq_41854911/article/details/119453790
- https://blog.csdn.net/heluan123132/article/details/76135401
NDEBUG 和 DEBUG 宏的用法
NDEBUG
宏是 Standard C 中定义的宏, 专门用来控制 assert()
的行为. 如果定义了这个宏, 则 assert
不会起作用.
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
...
C Standard 中规定了 assert
以宏来实现. <assert.h>
被设计来可以被多次包含, 其中一上来就 undef assert
, 然后由 NDEBUG
宏来决定其行为. 如:
#ifdef NDEBUG
#undef NDEBUG
#include <assert.h>
#define NDEBUG
#else
#include <assert.h>
#endif // #ifdef NDEBUG
将以上代码放在 c/cpp 最上方 (当然, 其后不能出现其它 #include <assert.h>
语句), 就可以保证 c/cpp 所在的编译单元中的 assert, 在 release 下也会触发 abort 行为.
NDEBUG
宏由于字面意思, 也被用于作为判断 debug/release
版本的宏, 不过这个是编译器, 环境相关的, 并不可靠.
比如 vc 中, 对生成的 release 版本项目, 默认会定义这个宏, 而 gcc 并没有定义, 得用 -DNDEBUG
参数来定义.
C++ Standard 中完全采用了 C 中的定义.
assert()
函数用法
assert 宏的原型定义在 <assert.h>
中, 其作用是如果它的条件返回错误, 则终止程序执行, 原型定义:
#include <assert.h>
void assert(int expression);
assert
的作用是现计算表达式 expression
, 如果其值为假 (即为 0), 那么它先向 stderr
打印一条出错信息, 然后通过调用 abort
来终止程序运行.
请看下面的程序清单 badptr.c:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
fp = fopen("test.txt", "w"); //以可写的方式打开一个文件, 如果不存在就创建一个同名文件
assert(fp); //所以这里不会出错
fclose(fp);
fp = fopen("noexitfile.txt", "r"); //以只读的方式打开一个文件, 如果不存在就打开文件失败
assert(fp); //所以这里出错
fclose(fp); //程序永远都执行不到这里来
return 0;
}
测试
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]# ./a.out
a.out: badptr.c:14: main: Assertion `fp' failed.
使用 assert
的缺点是, 频繁的调用会极大的影响程序的性能, 增加额外的开销.
在调试结束后, 可以通过在包含 #include <assert.h>
的语句之前插入 #define NDEBUG
来禁用 assert
调用, 示例代码如下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>
用法总结与注意事项:
1) 在函数开始处检验传入参数的合法性
如:
int resetBufferSize(int nNewSize)
{
//功能: 改变缓冲区大小,
//参数:nNewSize 缓冲区新长度
//返回值: 缓冲区当前长度
//说明: 保持原信息内容不变 nNewSize<=0 表示清除缓冲区
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}
2) 每个 assert 只检验一个条件, 因为同时检验多个条件时, 如果断言失败, 无法直观的判断是哪个条件失败
不好:
assert(nOffset >= 0 && nOffset + nSize <= m_nInfomationSize);
好:
assert(nOffset >= 0);
assert(nOffset + nSize <= m_nInfomationSize);
3) 不能使用改变环境的语句, 因为 assert 只在 DEBUG 生效, 如果这么做, 会使用程序在真正运行时遇到问题
错误:
assert(i++ < 100)
这是因为如果出错, 比如在执行之前 i=100
, 那么这条语句就不会执行, 那么 i++
这条命令就没有执行.
正确:
assert(i < 100);
i++;
4) assert
和后面的语句应空一行, 以形成逻辑和视觉上的一致感
5) 有的地方, assert
不能代替条件过滤
文章评论