当程序复杂了以后,bug难以避免,因此,为了快速地找到问题所在,写了这个调试接口,这个东西大概两年前写的,现在看来感觉没有太大的必要了,当出问题时,都习惯于用gdb调试了,这个接口趋于荒废了,不过毕竟是自己年轻时的作品,还是贴上来,留作纪念吧...
以下为什么要raise_exception呢?其实是为了gdb调试方便,因为通常gdb只有触发SIGSEGV时才会断掉,此时才可以用backtrace查看函数调用栈,所以我这里想当我们自己的某些条件不满足时,发送SIGUSR1信号,这时gdb同样会断掉,我们就可以好好查看调用栈,看到底是哪里出了问题。
另外还有一个,就是在return_val_if_fail里为什么后面要接可变参数呢,主要是可以提供更多的调试信息吧,或者额外的说明信息吧,比如
- char *ptr = calloc(1, 1024);
- return_val_if_fail(ptr != NULL, -1);
- return_val_if_fail(ptr != NULL, -1, "Memory Allocate failed : %p", ptr);
这个意思就是,如果 ptr != NULL 失败,就返回-1,同时提供额外的调试信息,可以说明具体是出了什么问题。当然,这个额外的调试信息你也可以不提供,不过那样的话在这个宏内调用snprintf就会报出警告提示说err_msg为空,为了避免这个警告,我通常在__VA_ARGS__前加了个空格,所以在后面需要判断用户是否提供了额外的调试信息,如果提供了,我才打印出来。
这个接口在我早期写的很多程序中都用到了,大家可以看看我贴上来的内存管理器,正是因为在写这个内存管理器中时出现了许多让人头疼的bug,而这些bug又通常埋藏地很深,找出来很费脑筋,所以才催生了写个调试接口的想法。事实证明,这个接口的确给我带来了很大的方便,在一些关键的地方放置这些语句,当程序没有问题时,可以用宏开关关掉这些调试机制即可,因此非常方便
- #ifndef _debug_h
- #define _debug_h
- #if !defined(RAISE_SIGNAL_DISABLED)
- #include <signal.h>
- static void raise_exception(void)
- {
- raise(SIGUSR1);
- }
- #else
- #define raise_exception() ((void)0)
- #endif
- /****************************************************************/
- /****************************************************************/
- #if !defined(DISABLE_D)
- #define D__ fprintf(stdout,"Running Over %s() at %s : %d\n",\
- __FUNCTION__,__FILE__,__LINE__);
- #else
- #define D__ ((void)0);
- #endif
- #if !defined(DISABLE_MSG)
- #define msg(std, ...) fprintf(std, __VA_ARGS__)
- #else
- #define msg(std, ...) ((void)0)
- #endif
- /****************************************************************/
- /****************************************************************/
- #define ERRMSG_LEN 128
- #define return_val_if_fail(p, ret, ...) do { \
- if(!!!(p)) { \
- char err_msg[ERRMSG_LEN] ; \
- snprintf(err_msg, ERRMSG_LEN, " "__VA_ARGS__); \
- \
- fprintf(stdout, \
- "\nUncaught exception assertion ("#p") failed" \
- "\nRaised in file: %s at function: %s in line: %d", \
- __FILE__, __FUNCTION__, __LINE__); \
- \
- if(err_msg[1]) \
- fprintf(stdout, "\nError Message >> %s\n", err_msg);\
- \
- raise_exception(); \
- \
- return ret; \
- } \
- } while(0)
- #define return_if_fail(p, ...) do { \
- if(!!!(p)) { \
- char err_msg[ERRMSG_LEN] ; \
- snprintf(err_msg, ERRMSG_LEN, " "__VA_ARGS__); \
- \
- fprintf(stdout, \
- "\nUncaught exception assertion ("#p") failed" \
- "\nRaised in file: %s at function: %s in line: %d", \
- __FILE__, __FUNCTION__, __LINE__); \
- \
- if(err_msg[1]) \
- fprintf(stdout, "\nError Message >> %s\n", err_msg);\
- \
- raise_exception(); \
- \
- return; \
- } \
- } while(0)
- #if !defined(DISABLE_SHOW)
- #define Show_Value(x, u) \
- fprintf(stdout, "\nCalled From %s() at %s : %d, "\
- "The Value of "#x" is %"#u"\n",\
- __FUNCTION__, __FILE__, __LINE__, x)
- #else
- #define Show_Value(x, u) ((void)0)
- #endif
- #endif
阅读(1851) | 评论(2) | 转发(0) |