__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 ...
随机推荐
- 【ZJOI2016】小星星
题目描述 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有 $n$ 颗小星星,用 $m$ 条彩色的细线串了起来,每条细线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这 ...
- Life of an Oracle I/O: tracing logical and physical I/O with systemtap
https://db-blog.web.cern.ch/blog/luca-canali/2014-12-life-oracle-io-tracing-logical-and-physical-io- ...
- JavaScript世界万物诞生记
作者:manxisuo链接:https://zhuanlan.zhihu.com/p/22989691来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 一. 无中生有 起 ...
- JavaScript this用法总结(**************************************)
JavaScript this用法总结 在JavaScript中,this关键字可以说是最复杂的机制之一.对this的作用机制缺乏比较深入的理解很容易在实际开发中出现问题. 1.this的作用 为什么 ...
- Android图片缓存之Bitmap详解(一)
前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. Bitmap: Bitmap是Android ...
- django忘记超级用户密码的解决方法
用Django shell: 1 python manage.py shell 然后获取你的用户名,并且重设密码: 1 2 3 4 from django.contrib.auth.models im ...
- elasticsearch 查询模板
简单版示例: 2.x版本(相比于1.x版本,使用bool替代filtered,使用must替代query) { "query": { "bool": { &qu ...
- mysql_config_editor使用简介
原文 : http://blog.itpub.net/29773961/viewspace-1817640/ ----------------------------------------- ...
- C 标准库 - <time.h>
C 标准库 - <time.h> 简介 time.h 头文件定义了四个变量类型.两个宏和各种操作日期和时间的函数. 库变量 下面是头文件 time.h 中定义的变量类型: 序号 变量 &a ...
- java性能监控工具jstat-windows
jstat Monitors Java Virtual Machine (JVM) statistics. This command is experimental and unsupported. ...