博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[zz]利用__FILE__, __LINE__, __FUNCTION__跟踪调试程序
阅读量:5308 次
发布时间:2019-06-14

本文共 6060 字,大约阅读时间需要 20 分钟。

转载自: 

作为一个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 <sys/param.h>
    #include <stdio.h>
    #include <stdarg.h>
    #include <time.h>
/*********************************************************************
*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,则程序运行到了哪里出了问题就会一目了然了。

转载于:https://www.cnblogs.com/zhangzhang/archive/2013/01/06/2847595.html

你可能感兴趣的文章
ubuntu 安装后的配置
查看>>
web前端之路,js的一些好书(摘自聂微东 )
查看>>
【模板】对拍程序
查看>>
【转】redo与undo
查看>>
解决升级系统导致的 curl: (48) An unknown option was passed in to libcurl
查看>>
Java Session 介绍;
查看>>
spoj TBATTLE 质因数分解+二分
查看>>
Django 模型层
查看>>
dedecms讲解-arc.listview.class.php分析,列表页展示
查看>>
Extjs6 经典版 combo下拉框数据的使用及动态传参
查看>>
【NodeJS】http-server.cmd
查看>>
研磨JavaScript系列(五):奇妙的对象
查看>>
面试题2
查看>>
selenium+java iframe定位
查看>>
P2P综述
查看>>
第五章 如何使用Burp Target
查看>>
Sprint阶段测试评分总结
查看>>
sqlite3经常使用命令&amp;语法
查看>>
linux下编译openjdk8
查看>>
【python】--迭代器生成器装饰器
查看>>