自定义调试信息宏及gcc技巧

[编程手记小技巧]自定义调试信息宏及gcc技巧 收藏

文中所讲的函数,可能是指使用宏定义的“宏函数”,也可能是指真正的函数。假设你不会混淆它们,也假设你能理解它们。

许多开源项目代码中都有自定义的调试信息的相关的函数。比如u-boot中(来自common.h头文件)

  1. #ifdef  DEBUG   
  2. #define debug(fmt,args...)  printf (fmt ,##args)   
  3. #define debugX(level,fmt,args...) if (DEBUG>=level) printf(fmt,##args);   
  4. #else   
  5. #define debug(fmt,args...)   
  6. #define debugX(level,fmt,args...)   
  7. #endif  /* DEBUG */   

如果定义了DEBUG这个宏,则使用debug会输出自定义的信息,如果没有定义,则什么也不会输出——不执行任何语句。

这种调试函数有N种形式,比如

 

  1. #ifdef DEBUG   
  2. #define debug_msg(format,...)   /   
  3.     fprintf(stdout,format,##__VA_ARGS__)  
  4. #else   
  5.   
  6. #define debug_msg(format,...)   
  7. #endif   /* DEBUG */   

我们要注意##这个符号的用法,它用于连接##前后的字符串,在debug_msg只有一个参数情况下,它的作用就显示出来了。它属于C/C++的范畴,而不是特定编译器的。

一个带详细信息的出错提示

  1. #define print_error(str)    /   
  2.     do  {            /  
  3.     fprintf(stderr, "Oh God!/nFile:%s Line:%d Function:%s:/n" ,/  
  4.          __FILE__, __LINE__, __func__); /  
  5.     perror(str);        /  
  6.     return  (EXIT_FAILURE);  /  
  7.     } while (0)  

它不仅打印导致出错的文件、行号、函数,还打印这个出错的原因。EXIT_FAILURE在系统中定义为1。当然,也可以使用exit(1),等等。

这里要注意一点,在linux中有一些习惯的约定,比如表示判断的函数,返回非零表示成功,返回0表示失败;表示操作性质的函数,返回0表示操作成功,返回非零表示操作失败。——经典地,strcmp这个函数,如果要比较的两个字符串相同,它是返回0的。

这里我们同样要注意一点,输出调试信息与出错信息是两回事,调试信息是帮助我们更好地理解程序的运行、各个变量或程序的走向,这些信息是可有可无 的。但是出错信息却不同,程序已经出错了,没理由也不能继续运行下去了。比如给某一指针分配内存空间,如果分配失败,我们必须返回或退出函数(有些面试题 会考这个的,山人见过)。这些是我们需要注意的。

上面说到可有可无,怎么实现?很简单,就是在你使用到的地方定义那个宏就行了(比如上面的例子中是DEBUG)。在u-boot中,如果在公共头文 件common.h中打开DEBUG宏,则所有调用debug的函数都会打印调试信息,这习惯可不好。因此,我们在需要的地方才打开调试宏。

此外,也可以利用gcc编译器的-D选项来打开调试宏。使用也简单,直接在-D后面添加调试宏就行了。比如

$ gcc -DDEBUG -g -o foo foo.c

当然,实际例子不会这么用的。

下面举一个山人在实践中的例子。

假设的背景:一个摄像头,在ARM开发板中的设备文件是“/dev/video1”,在PC平台中却是“/dev/video”。

是不是必须使用两套代码呢?没必要。我们可以在代码中这样定义

  1. #ifdef  __ARM__   
  2. #define device "/dev/video1"   
  3. #else   
  4. #define device "/dev/video"   
  5. #endif   

这样,我们可以在Makefile中指定CFLAGS为-D__ARM__,代码就不用进行修改了。这在开发、调试阶段很有用,在后面的阶段则可以不使用这种方法。

当然,解决问题的方法可以有多种,比如使用两个Makefile文件(当然,文件名不能相同,而且,编译器也需要改变),编译时,使用-f指定Makefile文件。

上面只是讲了一种方法,方法没有绝对的好与不好,找到合适自己的才是最好的。

                                                                                                    木草山人

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值