Chinaunix首页 | 论坛 | 博客
  • 博客访问: 33437
  • 博文数量: 12
  • 博客积分: 460
  • 博客等级: 下士
  • 技术积分: 125
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-18 14:19
文章分类

全部博文(12)

文章存档

2010年(12)

我的朋友
最近访客

分类: LINUX

2010-02-18 15:47:41

在客户项目那里混了半年,发现Top的客户确实是比我们牛逼。先说说调试的方法。
客户那边不依赖于GDB调试,因为他们可能觉得GDB依赖于系统实现,不利于移植吧,所以客户的程序完全是依赖于打印调试的。这点很佩服他们的软件规划能力和项目管理,实现能力。说老实话,如果换了一家中国公司,每人一个调试方法,要follow 一个rule是很不容易的。
  • 完善的调试菜单。调试菜单并不难实现,只是一个打印和字符接受的函数。在其中控制是开放某些打印信息。
  • 在每个模块中加上仔细规划打印输出,根据需求分成不同的基本。最好情况是在最高打印级别中可以可以发现所有的问题。打印级别可以很方便的动态控制。
  • 函数调用LOG
        如果能定位发生问题的模块,可以在该模块的在每个函数的调用入口加上打印一个函数名字+Enter,在返回处加上一个函数名字+Exit。对于每个模块用一个打印开关控制是否打印Trace信息。在调试菜单中控制这个打印开关。
       如果懒得加打印语句,可以利用gcc 的-finstrument-functions 选项来快速的加入调试信息。-finstrumnet-function会是的编译器在函数调用的开始和退出处调用
void __cyg_profile_func_enter (void *this_fn, void *call_site)
void __cyg_profile_func_exit  (void *this_fn, void *call_site)。 可以利用这两个函数来跟踪函数调用的过程。
在实现这两个函数时要加入__attribute__ ((no_instrument_function));以避免编译器再调用这两个函数的时候也调用__cyg_profile_func_enter 和 __cyg_profile_func_exit 而造成循环调用。
      可以用dladdr()来获得this_fn的文件和函数名。code如下:
#define _GNU_SOURCE  // 由于dladdr是GNU扩展,不是dl的标准函数,因此在这句话必须加在文件的开始处

#include
#include
void __cyg_profile_func_enter (void *this_fn, void *call_site) __attribute__ ((no_instrument_function));
void __cyg_profile_func_exit  (void *this_fn, void *call_site) __attribute__ ((no_instrument_function));

void __cyg_profile_func_enter (void *this_fn, void *call_site)
{
    Dl_info DLInfo;
    dladdr(this_fn, &DLInfo);
    printf("Enter file %s\n",DLInfo.dli_fname);
    printf("functio  %s\n",DLInfo.dli_sname);
   
}


void __cyg_profile_func_exit  (void *this_fn, void *call_site)
{
}


  • 关于打印堆栈。可以用
        #include
        void *array[10];
        char **strings;
        size_t size;
        size_t i;
        size = backtrace(array, 10);
        strings = backtrace_symbols(array, size);
        for(i=0;i        {
            printf ("%d, %p  ,%s\n",i,array[i],strings[i]);
        }
     该方法需要编译器支持。
     但是需要在编译的时候加上-rdynamic 否则只能输出在内存中的绝对地址。
   
    在没有-rdynamic的时候,关于如何找到动态库的运行时地址还需要研究。
    可以在系统运行的时候发送
SIGSEGV给应用程序,产生当前进程的Coredump来获取动态库中函数的运行是地址。
    用GDB获取backtrace的方法(在有-g选项的时候可以看到,不需要-rdynamic):
    list <*address>

    在没有-g的时候,又该如何呢?
   



阅读(906) | 评论(1) | 转发(0) |
0

上一篇:进程的前后台切换

下一篇:关于coredump

给主人留下些什么吧!~~

egmkang2011-03-17 16:51:05

这个不错啊