编程技巧之调试日志

1.宏定义开关方法

我们在调试程序的时候,经常会需要知道在运行时某些变量的状态(值),我们可以通过定义调试开关,来生成debug调试版本或者release最终发行版本程序,先看个简单的例子:

    void main(void)
    {
    
     
       int runtime_flag;//举例一个流程时的判断标志   
        /***注释标记1***
        省略一些变量定义或函数运行
        这些函数可能会影响runtime_flag的值
        ***************/    
       if(runtime_flag == 1)
       {
    
     
        /***注释标记2***
        省略一些函数运行
        这些函数可能会影响runtime_flag的值
        ***************/   
       }
       else
       {
    
    
        /***注释标记3***
        省略一些函数运行
        这些函数可能会影响runtime_flag的值
        ***************/     
       }
        /***注释标记4***
        省略一些函数运行
        这些函数可能会影响runtime_flag的值
        ***************/         
    }

以上我们举了一个比较简单的例子说明,在类似代码中,我们如果需要知道某一变量运行时的状态,比如想知道注释标记3处的runtime_flag的值,我们该怎么办?

一般调试,是通过编译调试软件进入调试debug模式下加断点等方法。

但是,很多场景下,尤其是产品项目已落地测试维护的产品,我们是没有办法在现场通过调试软件进行源码分析,此时通过预先的宏技巧,来实现调试开关就显得尤为关键。让我们直接上源码:

    /*宏调试开关*/
    #define debug
    /*显示打印信息所在的文件、行数、函数名以及需要print的信息*/
    #define DBG_PRINTF(fmt, args...)   \
    {
    
    
     printf("<<File:%s  Line:%d  Function:%s>> ", __FILE__, __LINE__, __FUNCTION__);\
     printf(fmt, ##args);\
    }
    
    void main(void)
    {
    
     
       int runtime_flag;//举例一个流程时的判断标志   
        /***注释标记1省略处***/
       #ifdef debug
       DBG_PRINTF("runtime_flag=%d\r\n",runtime_flag) ;
       #endif     
       if(runtime_flag == 1)
       {
    
     
        /***注释标记2省略处***/  
       }
       else
       {
    
    
        /***注释标记3省略处***/ 
       #ifdef debug
       DBG_PRINTF("runtime_flag=%d\r\n",runtime_flag) ;
       #endif  
       }
        /***注释标记4省略处***/         
    }

通过以上的宏定义开关,我们就可以知道标记1以及标记3处我们需要知道的变量值在运行到所在文件、行数、函数名、以及变量值是多少。在调试阶段我们可以宏定义debug,测试无问题后,可将debug宏定义注释,直接生成release版本,后续如果需要debug,再宏定义恢复,这就及其方便。

2.变量开关方法

上述宏定义技巧在切换为release版本时,还需要通过编译软件修改源码在进行操作,有没有什么方法可以在外部调试的情况下,直接切换debug模式状态或者release状态?让我们直接上源码:

    /*显示打印信息所在的文件、行数、函数名以及需要print的信息*/
    #define DBG_PRINTF(fmt, args...)   \
    {
    
    
     printf("<<File:%s  Line:%d  Function:%s>> ", __FILE__, __LINE__, __FUNCTION__);\
     printf(fmt, ##args);\
    }
    
    int debug = 1 ; // 全局变量,默认开关为打开状态
    
    void main(void)
    {
    
     
       int runtime_flag;//举例一个流程时的判断标志   
        /***注释标记1省略处***/
       if(debug == 1)
       DBG_PRINTF("runtime_flag=%d\r\n",runtime_flag) ;
       if(runtime_flag == 1)
       {
    
     
        /***注释标记2省略处***/  
       }
       else
       {
    
    
        /***注释标记3省略处***/ 
       if(debug == 1)
       DBG_PRINTF("runtime_flag=%d\r\n",runtime_flag) ;  
       }
        /***注释标记4省略处***/         
    }
    /*不同应用对象应用的中断形式不同,我们以外部输入触发中断举例*/
    void interrupt input_var ()
    {
    
    
    	  scanf("%d",&debug)  ;
    }

通过以上的变量开关,可以实现动态运行测试时就可以切换是否输出调试日志信息。

关于中断触发,不同的应用平台使用的方式方法不一样,统一抽象的思想是:

在流程动态运行中,输入debug值,会触发中断(不同的形式叫法不一样),这会改变debug值,从而实现动态的外部切换debug或release版本状态,也就是是否输出调试时我们希望看到的调试日志信息。

3.小结对比

让我们将两个方法做个对比:

  • 共同点:
    • 都可以在程序动态运行时,输出对应的调试日志信息;
    • 在debug版本模式下所占用空间类似。
  • 不同点:
    • 宏开关在relase版本下,由于未定义debug开关,所以之后的宏定义判断不占用程序空间,不会增加计算消耗;
    • 变量开关在切换relase版本时候只需要debug=0即可。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/caq_jw/article/details/112410343