标题
利用__FILE__, __LINE__, __FUNCTION__跟踪调试程序[zt 有一个定义可变参数宏的例子]
我是马甲
浏览(0) +
2007-09-10 10:10:43 发表
编辑
关键字:
利用__FILE__, __LINE__, __FUNCTION__跟踪调试程序[zt 有一个定义可变参数宏的例子] 作为一个Linux系统下的C程序员,你可能发现调试程序是个比较麻烦的工作,虽然已经有gdb,kgdb等专业的调试软件,但如果对这些软件运用不熟练是根本达不到调试程序找出bug的目的的。又或者你对gdb已经很熟了,但运行gdb开始调试后在哪里设置断点成了你头痛的问题?当然,你可以从程序开始就以单步运行step by step来调试程序,但这会耗去你很多时间。 如果你能很好地跟踪并记录程序的运行情况,那么一切将变得简单。下面我以一个实例说明我是如何操作的: 首先我有一个程序主体main,其代码如下: //////////////////////////////trace.c 开始/////////////////////////////////////////// /********************************************************************* *filename: trace.c *purpose: demonstrate how to trace program easily. We'll * get every source filename, function-name, and the * current line number wrote into a stream. The stream * can be a file descriptor or stdout *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *date time:2005-11-30 00:30 *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ #include "global.h" #include "MyFuncOne.h" #include "MyFuncTwo.h" int x; int main(int argc, char ** argv) { x = 5; dump(stdout, "now: x=%d", x); MyFuncOne(); MyFuncTwo(); dump(stdout, "now: x=%d", x); return 0; } //////////////////////////////trace.c 结束/////////////////////////////////////////// 这个main里面引用了global.h,MyFuncOne.h,MyFuncTwo.h等,global.h里面是一个宏定义,定义了dump宏,其内容如下: //////////////////////////////global.h 开始/////////////////////////////////////////// #ifndef GLOBAL_H #define GLOBAL_H #include "dump.h" /********************************************************************* *filename: global.h *purpose: dump function declare *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *date time:2005-11-30 00:30 *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ #ifdef DEBUG #define dump(fp, x...) debug_print(fp, __FILE__, __LINE__, __FUNCTION__, ##x); #else #define dump(fp, x...) #endif #endif //////////////////////////////global.h 结束/////////////////////////////////////////// global.h这里又引用了dump.h,其内容稍后再贴出来。 MyFuncOne.h和MyFuncTwo.h分别定义了两个函数MyFuncOne和MyFuncTwo,其内容如下: //////////////////////////////MyFuncOne.h 开始/////////////////////////////////////////// #ifndef MYFUNC_ONE_H #define MYFUNC_ONE_H #include "global.h" /********************************************************************* *filename: MyFuncOne.h *purpose: MyFuncOne function declare *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *date time:2005-11-30 00:30 *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ void MyFuncOne(); #endif //////////////////////////////MyFuncOne.h 结束/////////////////////////////////////////// //////////////////////////////MyFuncTwo.h 开始/////////////////////////////////////////// #ifndef MYFUNC_TWO_H #define MYFUNC_TWO_H #include "global.h" /********************************************************************* *filename: MyFuncTwo.h *purpose: MyFuncTwo function declare *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ void MyFuncTwo(); #endif //////////////////////////////MyFuncTwo.h 结束/////////////////////////////////////////// //////////////////////////////MyFuncOne.c 开始/////////////////////////////////////////// #include "MyFuncOne.h" extern int x; /********************************************************************* *filename: MyFuncOne.c *purpose: MyFuncOne function instance *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *date time:2005-11-30 00:30 *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ void MyFuncOne() { x *= -2; dump(stdout, "MyFuncOne, now: x=%d", x); } //////////////////////////////MyFuncOne.c 结束/////////////////////////////////////////// //////////////////////////////MyFuncTwo.c 开始/////////////////////////////////////////// #include "MyFuncTwo.h" extern int x; /********************************************************************* *filename: MyFuncTwo.h *purpose: MyFuncOne function declare *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *date time:2005-11-30 00:30 *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ void MyFuncTwo() { x++; dump(stdout, "MyFuncTwo, now: x=%d", x); } //////////////////////////////MyFuncTwo.c 结束/////////////////////////////////////////// 现在该是时候说dump了,先看看其实现: //////////////////////////////dump.h 开始/////////////////////////////////////////// #ifndef DUMP_H #define DUMP_H #include #include #include #include /********************************************************************* *filename: dump.h *purpose: debug_print function declare *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *date time:2005-11-30 00:30 *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ void debug_print(FILE * fp, const char * filename, const int line, const char * funcname, char *fmt, ...); #endif //////////////////////////////dump.h 结束/////////////////////////////////////////// //////////////////////////////dump.c 开始/////////////////////////////////////////// #include "dump.h" /********************************************************************* *filename: dump.c *purpose: debug_print function instance *wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com) *date time:2005-11-30 00:30 *Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途 * 但请遵循GPL *********************************************************************/ void debug_print(FILE * fp, const char * filename, const int line, const char * funcname, char *fmt, ...) { char buf[1024]; time_t t; struct tm * now; va_list ap; time(&t); now = localtime(&t); va_start(ap, fmt); fprintf(fp, "%04d-%02d-%02d %02d:%02d:%02d -- %s(%d):%s DEBUG:@\"", now -> tm_year + 1900, now -> tm_mon + 1, now -> tm_mday, now -> tm_hour, now -> tm_min, now -> tm_sec, filename, line, funcname); vsprintf(buf, fmt, ap); fprintf(fp, "%s\"@\n", buf); va_end(ap); } //////////////////////////////dump.c 结束/////////////////////////////////////////// 大家一定注意到:这个程序和大家一般写的程序并无大的区别,除了__FILE__, __LINE__, __FUNCTION__等几个宏和dump宏,__FILE__, __LINE__, __FUNCTION__是编译的时候已经内置了的几个宏,用来表明当前程序运行到了哪个源文件的哪一行,同时表明当前在哪个函数里面。而我们定义一个dump宏就是用来把这些信息送到一个文件句柄去。比如你的日志文件。这样,在任何程序需要的地方都可以加上一句dump来把需要的调试信息记录下来。 比如编译上述程序: gcc -DDEBUG trace.c dump.c MyFuncOne.c MyFuncTwo.c -o trace 然后运行程序可以得到如下结果: 2005-11-30 00:40:38 -- trace.c(22):main DEBUG:@"now: x=5"@ 2005-11-30 00:40:38 -- MyFuncOne.c(15):MyFuncOne DEBUG:@"MyFuncOne, now: x=-10"@ 2005-11-30 00:40:38 -- MyFuncTwo.c(15):MyFuncTwo DEBUG:@"MyFuncTwo, now: x=-9"@ 2005-11-30 00:40:38 -- trace.c(25):main DEBUG:@"now: x=-9"@ 第一行:显示在trace.c源文件的第22行处,即main函数内打印出:now: x=5; 第二行:显示在MyFuncOne.c源文件的第15行处,即MyFuncOne函数内打印出:MyFuncOne, now: x=-10; 第三行:显示在MyFuncTwo.c源文件的第15行处,即MyFuncTwo函数内打印出:MyFuncTwo, now: x=-9; 第四行:显示在trace.c源文件的第25行处,即main函数内打印出:now: x=-9; 如果程序加多点dump,则程序运行到了哪里出了问题就会一目了然了。
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.