C++ 调试技巧
2016-03-04 17:03
197 查看
在C++中有时会用到类似于头文件保护的技术,以便有选择的执行调试代码。基本思想是,程序可以包含一些用于调试的代码,但是这些代码只在开发程序的时候使用。当应用程序编写完成准备发布时,要先屏蔽掉调试代码。这种方法用到了两种预处理功能:assert和NDEBUG。
assert预处理宏
assert是一种预处理宏。所谓预处理宏其实就是一个预处理变量,它的行为有点类似于内联函数。assert宏使用一个表达式作为它的条件:
首先对expr求值,如果表达式为假,assert输出信息并终止程序的执行。如果表达式为真,assert什么也不做。
assert宏常用于检查“不能发生”的条件。例如,一个对输入文本进行操作的程序可能要求所有给定单词的长度都大于某个阀值。此时,程序可以包含一条如下所示的语句:
NDEBUG预处理变量
assert的行为依赖于一个名为NDEBUG的预处理变量的状态。如果定义了NDEBUG,则assert什么也不做。默认状态下没有定义NDEBUG,此时assert将执行运行时检查。
我们可以使用一个#define语句定义NDEBUG,从而关闭调试状态。
定义NDEBUG能避免检查各种条件所需的运行时开销,当然此时根本就不会执行运行时检查。因此,assert应该仅用于验证那些确实不可能发生的事。我们可以把assert当成调试程序的一种辅助手段,但是不能用它代替真正的运行时逻辑检查,也不能替代程序本身应该包含的错误检查。
除了使用assert外,也可以使用NDEBUG编写自己的条件调试代码。如果NDEBUG未定义,将执行#ifndef和#endif之间的代码;如果定义了NDEBUG,这些代码将被忽略。
C++编译器除了定义了之外,预处理器还定义了另外4个对于调试很有用的名字:
如下面的例子:
assert预处理宏
assert是一种预处理宏。所谓预处理宏其实就是一个预处理变量,它的行为有点类似于内联函数。assert宏使用一个表达式作为它的条件:
assert(expr);
首先对expr求值,如果表达式为假,assert输出信息并终止程序的执行。如果表达式为真,assert什么也不做。
assert宏常用于检查“不能发生”的条件。例如,一个对输入文本进行操作的程序可能要求所有给定单词的长度都大于某个阀值。此时,程序可以包含一条如下所示的语句:
assert(word.size()>threshold)
NDEBUG预处理变量
assert的行为依赖于一个名为NDEBUG的预处理变量的状态。如果定义了NDEBUG,则assert什么也不做。默认状态下没有定义NDEBUG,此时assert将执行运行时检查。
我们可以使用一个#define语句定义NDEBUG,从而关闭调试状态。
定义NDEBUG能避免检查各种条件所需的运行时开销,当然此时根本就不会执行运行时检查。因此,assert应该仅用于验证那些确实不可能发生的事。我们可以把assert当成调试程序的一种辅助手段,但是不能用它代替真正的运行时逻辑检查,也不能替代程序本身应该包含的错误检查。
除了使用assert外,也可以使用NDEBUG编写自己的条件调试代码。如果NDEBUG未定义,将执行#ifndef和#endif之间的代码;如果定义了NDEBUG,这些代码将被忽略。
void pring(const int ia[], size_t size) { #ifndef NDEBUG // __func__ 编译器定义的一个局部静态变量,用于存放函数的名字 cerr << __func__ << ":array size is " << size << endl; #endlf }
C++编译器除了定义了之外,预处理器还定义了另外4个对于调试很有用的名字:
名字 | 作用 |
---|---|
__func__ | 当前调试的函数名字 |
__FILE__ | 存放文件名的字符串字面值 |
__LINE__ | 存放当前行号的整型字面值 |
__TIME__ | 存放文件编译时间的字符串字面值 |
__DATE__ | 存放文件编译日期的字符串字面值 |
if(word.size() < threshold) cerr << "Error: " << __FILE__ << ": in function " << __func__ << " at line " << __LINE__ << endl << " Compiled on " << __DATA__ << " at " << __TIME__ << endl;
相关文章推荐
- gsoap生成c++框架
- c语言的编程格式
- C++ 错误: ‘std::vector<float> feat’的声明隐藏了一个形参
- [C++]lambda表达式
- C++ stringstream的使用 类型转换以及字符分离(功能类似split)
- 作业 c++编写
- 百练2801:填词
- 最近要开始准备找工作了,开始温习(yu xi)一下忘记的C语言知识
- C++面试常见的几个库函数详解
- C++中虚函数是怎样实现的
- C语言实现双向非循环链表(带头结点尾结点)的节点插入
- C语言中const有什么用途
- loadrunner11安装出现Microsoft Visual c++2005 sp1安装失败
- C++中typedef struct和struct的用法
- C++中class与struct的区别
- 利用C++日期类实现简单的日期计算器
- C语言小结
- c语言各类型转换
- c++ inline函数
- c++ inline函数