第六篇:使用预处理器帮助调试

前言

       你是否遇到过以下情况?

       情况一:为了调试方便,代码中夹杂各种cout语句。当调试好了,把这些语句删了,运行“正式版”后,又发现新问题,只得把这些cout语句一个个添加回去再进行调试。如此不断循环。

       情况二:希望在代码中获取到源文件的文件名,当前代码行号,编译时间等信息。

       情况三:纠结于是否实现某些概率极低(几乎不存在)的错误检测

       如果有,那么这篇随笔适合你,或者说,预处理器带来的调试技术适合你。

技巧一:设置调试区代码开关

       请看下面的源代码:

 1 #include <iostream>
 2  
 3 using namespace std;
 4  
 5 int main()
 6 {
 7     /*
 8     * 源代码区一
 9     */
10 
11     #ifdef DEBUG1
12     cout << "DEBUG1" << endl;
13     #endif
14  
15     /*
16      * 源代码区二
17     */
18 
19     #ifdef DEBUG2
20     cout << "DEBUG2" << endl;
21     #endif
22 
23     /*
24      * 源代码区三
25     */
26 
27     return 0;
28  }

       两段包含cout语句的代码段都是调试语句,而两个宏DEBUG1和DEBUG2就是所谓的开关。现在假设我想执行上面的那段调试代码,则可以输入以下指令打开DEBUG1开关并完成编译(这条命令等效于在源文件开头加上#define DEBUG1再编译):

1 g++ -DDEBUG1 1.cpp -o run

       运行结果如下:

  

  结果显示DEBUG1开关对应的调试语句得到执行。可以用同样的方法操纵开关DEBUG2及其对应调试代码。明白了吧,你可以通过打开开关自由地选择需要编译并运行的调试区代码

技巧二:使用预定义宏获取相关信息

       预处理器提供了一些预定义的宏可获取编译,文件的相关信息,参见下面代码:

 1 #include <iostream>
 2 
 3 using namespace std; 
 4 
 5 int main()
 6 {
 7     cout << "文件名: " << __FILE__ << endl;
 8     cout << "当前行号: " << __LINE__ << endl;
 9     cout << "编译日期: " << __DATE__ << endl;
10     cout << "编译时间: " << __TIME__ << endl;
11 
12     return 0;
13 }

       运行结果:

       

技巧三:使用assert断言宏确保某个条件不发生

  基本格式为 assert(表达式)。当表达式为真,语句不做任何事情,否则语句输出错误并终止程序执行,请看下面代码:

 1 #include <iostream>
 2 #include <cassert>    // 要使用assert断言宏必须包含这个头文件
 3  
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     int t=0;
 9     cin >> t;
10 
11     assert (t !=0);
12     cout << "t: " << t << endl;
13  
14     return 0;
15 }

       assert在这里的作用是确保t不等于0。如果t=0,程序会弹出错误并停止运行。编译代码并运行,

       当输入为0时运行结果:

       

       当输入其他数字时运行结果:

       

       最后要强调的是,assert只是调试工具,它绝对不能代替逻辑检查参与到异常处理中

posted @ 2017-01-26 20:09  穆晨  阅读(487)  评论(0编辑  收藏  举报