Chinaunix首页 | 论坛 | 博客
  • 博客访问: 192650
  • 博文数量: 27
  • 博客积分: 725
  • 博客等级: 上士
  • 技术积分: 347
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-04 09:01
文章分类

全部博文(27)

文章存档

2012年(15)

2011年(12)

分类: C/C++

2012-03-27 19:19:07

当程序复杂了以后,bug难以避免,因此,为了快速地找到问题所在,写了这个调试接口,这个东西大概两年前写的,现在看来感觉没有太大的必要了,当出问题时,都习惯于用gdb调试了,这个接口趋于荒废了,不过毕竟是自己年轻时的作品,还是贴上来,留作纪念吧...
 
以下为什么要raise_exception呢?其实是为了gdb调试方便,因为通常gdb只有触发SIGSEGV时才会断掉,此时才可以用backtrace查看函数调用栈,所以我这里想当我们自己的某些条件不满足时,发送SIGUSR1信号,这时gdb同样会断掉,我们就可以好好查看调用栈,看到底是哪里出了问题。
 
另外还有一个,就是在return_val_if_fail里为什么后面要接可变参数呢,主要是可以提供更多的调试信息吧,或者额外的说明信息吧,比如

  1. char *ptr = calloc(1, 1024);
  2. return_val_if_fail(ptr != NULL, -1);
  3. return_val_if_fail(ptr != NULL, -1, "Memory Allocate failed : %p", ptr);
这个意思就是,如果 ptr != NULL 失败,就返回-1,同时提供额外的调试信息,可以说明具体是出了什么问题。当然,这个额外的调试信息你也可以不提供,不过那样的话在这个宏内调用snprintf就会报出警告提示说err_msg为空,为了避免这个警告,我通常在__VA_ARGS__前加了个空格,所以在后面需要判断用户是否提供了额外的调试信息,如果提供了,我才打印出来。
 
这个接口在我早期写的很多程序中都用到了,大家可以看看我贴上来的内存管理器,正是因为在写这个内存管理器中时出现了许多让人头疼的bug,而这些bug又通常埋藏地很深,找出来很费脑筋,所以才催生了写个调试接口的想法。事实证明,这个接口的确给我带来了很大的方便,在一些关键的地方放置这些语句,当程序没有问题时,可以用宏开关关掉这些调试机制即可,因此非常方便
  1. #ifndef _debug_h
  2. #define _debug_h

  3. #if !defined(RAISE_SIGNAL_DISABLED)

  4. #include <signal.h>

  5. static void raise_exception(void)
  6. {
  7.     raise(SIGUSR1);
  8. }

  9. #else

  10. #define raise_exception()    ((void)0)

  11. #endif
  12. /****************************************************************/    
  13. /****************************************************************/
  14. #if !defined(DISABLE_D)

  15. #define D__ fprintf(stdout,"Running Over %s() at %s : %d\n",\
  16.             __FUNCTION__,__FILE__,__LINE__);

  17. #else

  18. #define D__ ((void)0);

  19. #endif

  20. #if !defined(DISABLE_MSG)

  21. #define msg(std, ...) fprintf(std, __VA_ARGS__)

  22. #else

  23. #define msg(std, ...) ((void)0)

  24. #endif
  25. /****************************************************************/    
  26. /****************************************************************/
  27. #define ERRMSG_LEN 128

  28. #define return_val_if_fail(p, ret, ...) do {                \
  29.         if(!!!(p)) {                                         \
  30.             char err_msg[ERRMSG_LEN]    ;                    \
  31.             snprintf(err_msg, ERRMSG_LEN, " "__VA_ARGS__);    \
  32.                                                             \
  33.             fprintf(stdout,                                 \
  34.                 "\nUncaught exception assertion ("#p") failed"         \
  35.                 "\nRaised in file: %s at function: %s in line: %d", \
  36.                     __FILE__, __FUNCTION__, __LINE__);                \
  37.                                                                     \
  38.             if(err_msg[1])                                             \
  39.                 fprintf(stdout, "\nError Message >> %s\n", err_msg);\
  40.                                                                     \
  41.             raise_exception();                                        \
  42.                                                                     \
  43.             return ret;                                                \
  44.         }                                                            \
  45.     } while(0)

  46. #define return_if_fail(p, ...) do {                            \
  47.         if(!!!(p)) {                                         \
  48.             char err_msg[ERRMSG_LEN]    ;                    \
  49.             snprintf(err_msg, ERRMSG_LEN, " "__VA_ARGS__);    \
  50.                                                             \
  51.             fprintf(stdout,                                 \
  52.                 "\nUncaught exception assertion ("#p") failed"         \
  53.                 "\nRaised in file: %s at function: %s in line: %d", \
  54.                     __FILE__, __FUNCTION__, __LINE__);                \
  55.                                                                     \
  56.             if(err_msg[1])                                             \
  57.                 fprintf(stdout, "\nError Message >> %s\n", err_msg);\
  58.                                                                     \
  59.             raise_exception();                                        \
  60.                                                                     \
  61.             return;                                                    \
  62.         }                                                            \
  63.     } while(0)

  64. #if !defined(DISABLE_SHOW)

  65. #define Show_Value(x, u) \
  66.     fprintf(stdout, "\nCalled From %s() at %s : %d, "\
  67.         "The Value of "#x" is %"#u"\n",\
  68.         __FUNCTION__, __FILE__, __LINE__, x)

  69. #else

  70. #define Show_Value(x, u) ((void)0)

  71. #endif

  72. #endif


阅读(1857) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

jmy24462672012-04-01 07:41:16

GFree_Wind: 大致看了看,还行。
楼主使用snprintf时,有时做了size-1,有时没做-1。
对于snprintf来说,size是不需要减1的,它可以保证安全。
因此err_msg[ERRMSG_LEN - 1].....
多谢您提醒,这个问题已经更正了,欢迎来访

GFree_Wind2012-03-29 11:57:12

大致看了看,还行。
楼主使用snprintf时,有时做了size-1,有时没做-1。
对于snprintf来说,size是不需要减1的,它可以保证安全。
因此err_msg[ERRMSG_LEN - 1] = '\0';  也是没有必要的。