我是不喜欢用类似VC下的F5,F10。曾经很喜欢用。被代码逻辑逼的没招了。所以不喜欢用了。

比如,错误是根据动态数据,产生的行为错误,无论是该写的未写,还是不该写的写了。指针跑飞什么等等,无非就是上述两个错导致。但要找到具体原因,F5,F10根本不够。所以索引不用了。

这里介绍一下我现在的方法。不过注明这不是LOG。

一个头文件。大体如下:

 #ifndef _debug_H_
#define _debug_H_ #include <stdlib.h>
#include <stdio.h>
#include <stdarg.h> #ifndef UNDEBUG_FILE
#define DEBUG_FLAG 1
#else
#define DEBUG_FLAG 0
#endif #if (DEBUG_FLAG == 1) static unsigned int __sdebug_time = ;
#define __debug_Msg_Size 1024
static char __pdebug_Msg[__debug_Msg_Size];
//注意下面的__attribute__不是C标准。。。。
static void __debug_info(const char *prefix,const char *fmt, ...) __attribute__((format (printf, , )));
#define __NEXT_DBG_TIME() do{sdebug_time++;}while(0)
#define __PRINT_POS() do {fprintf(stderr,"%s(%d){%s}",__FILE__,__LINE__,__func__);}while(0)
#define __FUNC_LOG() do{__PRINT_POS();fprintf(stderr,": t = %d ",__sdebug_time++);} while(0)
#define __FUNC_LOGn() do{__FUNC_LOG();fprintf(stderr,"\n");} while(0)
#define __PRINT_POS_exp(exp) do{__PRINT_POS();fprintf(stderr,"| (%s):",#exp);}while(0)
#define __PRINT_POS_P_exp(prefix,exp) do{__PRINT_POS();fprintf(stderr,"|<%s> (%s):",prefix,#exp);}while(0)
#define __PRINT_POS_expn(exp) do{__PRINT_POS_exp(exp);fprintf(stderr,"\n");}while(0)
#define __PRINT_POS_P_expn(prefix,exp) do{__PRINT_POS_P_exp(prefix,exp);fprintf(stderr,"\n");}while(0)
#define __ASSERT(exp) do{if (exp){}else{__PRINT_POS_P_expn("ASSERT ERROR",exp);}}while (0)
#define __ASSERT_EXIT(exp) do{if (exp){}else{__PRINT_POS_P_expn("ASSERT ERROR",exp);exit(1);}}while (0) #define __debug_info_LOG(exp,PREFIX,fmt,...) do{if (exp){__PRINT_POS_P_exp(PREFIX,exp);__debug_info(PREFIX,fmt,__VA_ARGS__);}}while (0) #define __ASSERT_LOG(exp,fmt,...) __debug_info_LOG(exp,"ASSERT!",fmt,__VA_ARGS__)
#define __ERROR_LOG(exp,fmt,...) __debug_info_LOG(exp,"ERROR!",fmt,__VA_ARGS__)
define __BEFORE_LOG(N,fmt,...) do {__debug_info_LOG((N) < __sdebug_time,"BEFORE!",fmt,__VA_ARGS__);__NEXT_DBG_TIME()}while()
#define __AFTER_LOG(N,fmt,...) do {__debug_info_LOG((N) >= __sdebug_time,"AFTER!",fmt,__VA_ARGS__); __NEXT_DBG_TIME();}while(0)
static void __debug_info(const char *prefix,const char *fmt, ...) {
va_list params;
va_start(params, fmt);
__ASSERT_EXIT((__pdebug_Msg) && (__pdebug_Msg_Size ));
vsnprintf(__pdebug_Msg, __pdebug_Msg_Size, fmt, params);
if (prefix){
fprintf(stderr, " %s %s\n", prefix, __pdebug_Msg);
}else{
fprintf(stderr, " %s\n", __pdebug_Msg);
}
va_end(params);
}
#else
#define __NOP do{}while(0)
#define __NEXT_DEBUG_TIME() __NOP
#define __FUNC_LOGn() __NOP
#define __FUNC_LOG() __NOP
#define __PRINT_POS_Sn(exp) __NOP
#define __PRINT_POS_S(exp) __NOP
#define __ASSERT(exp) __NOP
#define __ASSERT_EXIT(exp) __NOP
#define __debug_info_LOG(exp,PREFIX,fmt,...) __NOP
#define __ASSERT_LOG(exp,fmt,...) __NOP
#define __ERROR_LOG(exp,fmt,...) __NOP
#define __BEFORE_LOG(N,fmt,...) __NOP
#define __AFTER_LOG(N,fmt,...) __NOP #endif
#endif

上面

  UNDEBUG_FILE 

是如下用法,如果你觉得加了一对debug信息太乱,那么整体C文件(模块)暂时没错可以如下

 ...
#define UNDEBUG_FILE
#include "debug.h"
 __FUNC_LOGn();

可以写在每个函数的入口。这对跟踪函数之间的调用很有帮助(注意不是LOG,LOG打印这些就是没事找事了)

 __PRINT_POS_Sn

主要是,例如指针跑飞,可以在各个地方加插该内容,以判断是否经过该地方。其和

 __FUNC_LOGn();

输出是一样,但前者不影响sdebug_time。可以给出文件路径,行号,函数名和位置。一些输出情况如下:

 src/graph.c(){create_graph_abs_by_ID}: t =
src/graph_abstract.c(){refresh_graph_abs}: t =
src/graph_abstract.c(){refresh_graph_abs}: t =
src/graph_abstract.c(){refresh_graph_abs}|<ASSERT!> (): N =
src/graph_abstract.c(){refresh_graph_abs}: t =
src/graph.c(){create_graph_abs_by_ID}: t =

上面的内容就是上述头文件被#include到graph.c ,graph_abstract.c中,对应调用

 __FUNC_LOGn();
以及
__ASSERT_LOG(,"N = %d",N);

的结果。需要注意,__ASSERT_LOG,我和传统的__ASSERT是反过来的。此处表示,断言成立下,才LOG信息到stderr中。

 src/graph_abstract.c(){refresh_graph_abs}: t = 

实际上表示对

 __sdebug_time

第3次累加的位置。其实比如该文件对应累加

 __sdebug_time

运行了6000次后才出现某个情况出错,则可以使用

 __AFTER_LOG

__BEFORE_LOG则是反过来。

 __ASSERT_LOG
 

这相对F5,F9,F10,仅针对静态代码,进行断点要方便的多。当然你要额外增加一堆if判断,再加F9,我也没意见。哈。

http://www.oschina.net/question/249672_59411

vs不支持 __func__ 用 __FUNCTION__ 代替

最新文章

  1. [Android]使用Dagger 2来构建UserScope(翻译)
  2. Numpy 中一维数据转置的几种方法
  3. 转载-- http接口、api接口、RPC接口、RMI、webservice、Restful等概念
  4. STL --- UVA 123 Searching Quickly
  5. 基于url的权限管理
  6. Android源代码分析-资源载入机制
  7. css伪类的组合用法
  8. win7彻底卸载iis
  9. 利用Tess4J实现图片识别
  10. Oracle数据库在plsql中文乱码,显示问号????
  11. css 圆形头像
  12. IO多路复用的机制:select、poll、epoll
  13. Django ORM字段类型 单表增删改查 万能的双下划线
  14. XtraEditors一、总体介绍
  15. gulp 常用插件汇总
  16. 今天使用VS2012遇到一个问题:&quot;链接器工具错误 LNK2026 XXX模块对于 SAFESEH 映像是不安全的&quot;
  17. YaoLingJump开发者日志(七)
  18. Suse系统磁盘文件损坏恢复
  19. unity摄像机移动滑动
  20. 各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解

热门文章

  1. SD 胡策 Round 1 T3 彩尾巴猹的二进制数
  2. GRPC协议的相关原理
  3. 从零开始开发iPhone,教你如何在真机调试iPhone应用程序
  4. Spring HTTP Service
  5. SWF代码分析与破解之路 (YueTai VIP视频信息获取工具) Socket续篇
  6. JSP自己定义标签继承哪个类
  7. 树莓派 Zero W——随身钥匙扣
  8. 关于CUDA两种API:Runtime API 和 Driver API
  9. UIView 的 autoresizingMask 属性 详解。
  10. 在Fedora 25中更换openjdk为oracle jdk