__FILE__,__LINE__,__func__ 真好用,DEBUG利器啊!
我是不喜欢用类似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
上面
是如下用法,如果你觉得加了一对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__ 代替
__FILE__,__LINE__,__func__ 真好用,DEBUG利器啊!的更多相关文章
- __FILE__,__LINE__,FUNCTION__
__FILE__,__LINE__,FUNCTION__实现代码跟踪调试 ( linux 下c语言编程 ) 先看下简单的初始代码:注意其编译运行后的结果. root@xuanfei-desktop:~ ...
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程 )
root@xuanfei-desktop:~/cpropram/2# cat global.h //头文件#ifndef CLOBAL_H #define GLOBAL_H ...
- __FILE__,__LINE__,FUNCTION__实现代码跟踪调试
转:http://www.cnitblog.com/zouzheng/archive/2007/08/31/32691.aspx 先看下简单的初始代码:注意其编译运行后的结果. root@xuanfe ...
- C语言中预定义符 __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__ 的使用演示
本文演示了C语言中预定义符 __FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__ 的使用. 这几个预定义符的名称就没必要再介绍了,顾名思义嘛. // ...
- C/c++几个预定义的宏:__DATE__,__TIME__,__FILE__,__LINE__
一边情况下,C/C++编译器会内置几个宏,这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息. ANSI C标准中有几个标准预定义宏(也是常用的): __ ...
- Debug 利器:pstack & strace
工作中难免会遇到各种各样的 bug,对于开发环境 or 测试环境的问题还好解决,可以使用 gdb 打断点或者在代码中埋点来定位异常; 但是遇到线上的 bug 就很难受了,由于生产环境不能随意替换.中断 ...
- C标准中一些预定义的宏,如__FILE__,__func__等
C标准中一些预定义的宏 C标准中指定了一些预定义的宏,对于编程经常会用到.下面这个表中就是一些常常用到的预定义宏. 宏 意义 __DATE__ 进行预处理的日期(“Mmm dd yyyy”形式的字符串 ...
- 六.__FILE__ , __LINE__ 与调试日志
很多人可能不知道,C\C++编译器提供了一套针对代码文件的宏定义,它们能够帮助开发者更好的定位代码的BUG. __FILE__ 该宏定义是一个字符串,存储着当前代码文件的完整路径 __LINE__ 该 ...
- python 的__FILE__,__LINE__功能实现
在C语言里,__FILE__和__LINE__给调试提供了很大的方便,今晚在写PYTHON的时候想到,PYTHON是否有类似的功能实现呢? GOOGLE一番发现两个方法,试验一下下面这句:print ...
随机推荐
- JDBC_完整版
1,新建WEB项目:JDBC 2,导入驱动 将mysql-connector-java-5.0.8-bin.jar包放入web-inf目录下面的lib目录中 3,新建User类,放入entity包中 ...
- 【sublime text 3】sublime text 3 汉化
快捷键:Ctrl+Alt+P 输入快捷键Ctrl+Shift+P 在出现的文本框中输入Install Package(或直接输入“ip”)选中packageControl:Install Packag ...
- 谈oracle数据比对(DBMS_COMPARISON)
今天是2014-08-19,我今天收到csdn给我发的申请博客专家的邀请,自己感觉实在羞愧啊. 自从换了工作也一直没有精力在写点东西了.今天我一个同事,在群里贴出了一个数据比对的包(DBMS_COMP ...
- Java并发学习 & Executor学习 & 异常逃逸 & 同步互斥Best Practice & wait/notify, conditon#await/signal
看了这篇文章:http://www.ciaoshen.com/2016/10/28/tij4-21/ 有一些Java并发的内容,另外查了一些资料. 朴素的Thread 首先,Java中关于线程Thre ...
- C++学习总结2
链接上一篇日志,下面介绍下C++里面的其他内容 补充上一届里面的异常处理代码: try { cout << "try num" << endl; throw ...
- xcode 5.0 以上去掉icon高亮方法&iOS5白图标问题
之前的建议方法是把在xxx.info.plist文件里把 icon already includes gloss and bevel effects 设置YES 在Xcode5下,重复实现不成功,今天 ...
- EasyUI datagrid border处理,加边框,去边框,都可以,easyuidatagrid
下面是EasyUI 官网上处理datagrid border的demo: 主要是这句: $('#dg').datagrid('getPanel').removeClass('lines-both li ...
- *Android 多线程下载 仿下载助手(改进版)
首先声明一点: 这里的多线程下载 并非指的 多个线程下载一个 文件.而是 每一个线程 负责一个文件. 真正的多线程 希望后面能给大家带来. ------------- 欢迎 爱学习的小伙伴 加群 ...
- UVA 10526 - Intellectual Property (后缀数组)
UVA 10526 - Intellectual Property 题目链接 题意:给定两个问题,要求找出第二个文本抄袭第一个文本的全部位置和长度,输出前k个,按长度从大到小先排.长度一样的按位置从小 ...
- 生产制造追溯系统-通过微信小程序实现移动端报表平台
前言 前两篇文章主要梳理了一下在生产过程中如何更高效.更稳定的实现条码打印,有不少园子里的朋友私信我,互相讨论了一些技术方面的问题,双方都各有收获,再此感谢博客园提供的这个交流平台,让五湖四海的朋友能 ...