zoukankan      html  css  js  c++  java
  • 调试技巧总结

      以下内容总结自debug hacks一书的高手们的调试技术一章

      1.strace的使用技巧

        strace name,以这样的方式运行程序,可以查看到程序运行时的系统调用,仅仅是系统调用。可以看到系统调用失败时的传参,或者卡在哪个函数位置等等。

        -i选项可以看到每个系统调用的地址,那样在使用gdb调试时可以加断点。

        -p选项可以attach上已经正在运行的程序

        -o可以指定输出文件

        -t和-tt可以指定系统调用时间,分别以秒和毫秒为单位。

      2.objdump的使用技巧

        objdump反汇编之后的文件往往很难看出来对应于c程序中的哪一行代码,这个时候可以指定-S和-l选项分别显示出源文件中的代码和行号,程序需要包含有调试信息,最好是没有优化选项的文件,但不一定完全对应,可以作为参考。

      3.valgrind的使用技巧

        valgrind可以对缓存,堆进行评测,检测POSIX线程冲突等。

        最常用的内存检测,--tool=memcheck这个工具是valgrind的默认工具,可以不指定。

        可以检测的内容有,内存泄露,非法内存访问,读取未初始化区域,访问已释放区域,内存双重释放,非法栈操作等等。但是valgrind对于栈上的空间检测不是很好。

      4.kprobe的使用

        这个属于内核调试技术,可以在不重新编译内核的基础上,在任何一个函数内加打印,或者做其他任何处理,当然需要有内核源码,做一个合适的操作。

        比较好的一点是可以显示栈跟踪。这在调试中属于很好的技术。

      5.jprobe的使用

        与kprobe相同,可以检测任何一个内核函数的使用情况,但是jprobe的优点在于侦测函数的参数和被侦测函数的参数一样,可以很方便的打印出传参,而不像kprobe需要通过堆栈或者寄存器推理。

        其实我觉得以上两个工具对应于gdb就是断点。

      6.kprobe的强大之处

        kproble强大他可以插入内核任意位置,而不像jprobe只能插入在函数的开头处,包括他还在可以插在某条指令执行后还是某条指令执行前。

      7.kprobe替换内核函数

        kprobe可以替换内核中的某个函数,这样就可以在内核不重新编译的情况下,调试某个函数的情况。

      8.KAHO替换应用程序函数

        类似于上一个kprobe的功能,这样可以省的再次编译大型的应用程序。

      9.systemtap的使用

        这个工具是利用kprobe实现的一个工具,但是他是类似于脚本语言的方式来使用的,更加方便。功能有,查看堆栈,内部数据,等等。在应用程序的调试中就是gdb工具。

      10./proc/meminfo中的宝藏

        这个可以用作内存检测,他与valgrind相比,valgrind必须在程序运行结束时才给出测试结果,但这个可以直接实时看到。

      11./proc/<pid>/mem快速读取进程的内容

        和gdb或者ptrace一样,是查看内存的功能,但是速度上要快。

      12.oom killer

        当内存不足时,系统会对每个应用进程进行评分,评分最高者被关闭。

      13.错误注入

        一般来讲,malloc都会是成功的,但是这样就很难检测一些如果分配失败时导致的错误。那么这个功能就是提高分配失败的概率,或者说指定分配失败。

        需要连接一个failmalloc的库。方便测试失败情况。

        这个的使用非常方便,首先到failmalloc的官网下载他的代码,并编译和安装他,

        在每次运行时指定env的LD_PRELOAD参数为库所在目录及库名称,

        另外一个这个库支持指定选项,有四个

        FAILMALLOC_PROBABILITY

          specifies how often it should fail between 0.0 and 1.0.

          这个选项为失败的概率

        FAILMALLOC_INTERVAL

          specifies the interval of failures.

          这个选项为每几次malloc出现一次失败。

        FAILMALLOC_TIMES

          specifies how many times failures may happen at most.

          指定失败次数的上限

        FAILMALLOC_SPACE

          specifies the size of free space where memory can be allocated safely in bytes.

          指定申请内存失败的上限,即低于或者等于该值才会申请失败,超过该值必定成功。

      14.oprofile的使用

        这个工具可以查看一个程序的性能,比如l2级缓存的命中,各个函数的运行时间等等,并且这个工具可以生成图表。

        最常用的是各个函数的运行时间。

        类似的工具还有gprof,但是功能上差很多

        另外一个要注意的是,oprofile在虚拟机下不支持按事件计数。比较明显的是各个函数的运行时间检测不支持。

        下面详细描述一次oprofile的使用过程:

        源码:

        

    #include <stdio.h>

    int fun(int s,int i)
    {
    printf("s = %d , i = %d ",s,i);
    s = s+i;
    return s;
    }


    int main()
    {
    int i = 0;
    int sum = 0;
    for(;i<0x10000;i++)
    sum = fun(sum,i);
    printf("sum = %x ",sum);
    return 0;
    }

        接着是初始化oprofile

        [root@localhost oprofile-1.1.0]# opcontrol --init

        指定监听事件,这里使用默认事件,在cpu的时钟下采样,每10000个时钟采一次,不记录内核,只记录应用程序

        [root@localhost oprofile-1.1.0]# opcontrol --event=CPU_CLK_UNHALTED:10000:0:0:1

        开始分析

        [root@localhost oprofile-1.1.0]# opcontrol --start
        Using 2.6+ OProfile kernel interface.
        Using log file /var/lib/oprofile/samples/oprofiled.log
        Daemon started.
        Profiler running.

        运行程序,结束之后,停止分析

        [root@localhost oprofile-1.1.0]# opcontrol --stop

        查看结果

    [root@localhost oprofile-1.1.0]# opreport --merge=cpu -d a.out
    CPU: Core 2, speed 2666.13 MHz (estimated)
    Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 10000
    Processes with a thread ID of 32720
    Processes with a thread ID of all
    vma samples % samples % symbol name
    004004c4 226 61.9178 756 59.9524 fun
    004004c4 12 5.3097 34 4.4974
    004004cc 4 1.7699 25 3.3069
    004004da 2 0.8850 17 2.2487
    004004e7 4 1.7699 20 2.6455
    004004ec 23 10.1770 97 12.8307
    004004ef 130 57.5221 378 50.0000
    004004f2 32 14.1593 96 12.6984
    004004f5 19 8.4071 89 11.7725
    004004f7 139 38.0822 505 40.0476 main
    0040050f 3 2.1583 18 3.5644
    00400519 3 2.1583 23 4.5545
    0040051e 7 5.0360 25 4.9505
    00400521 92 66.1871 299 59.2079
    00400525 9 6.4748 33 6.5347
    0040052c 25 17.9856 107 21.1881

        这里的a.out是指定镜像,只查看该程序的函数。可以看出,main函数和fun函数各占了本次运行的比例。这只是一个简单的例子,如果对于一个大型的程序,就可以针对这个结果,优化函数,

         这里还可以查看代码级的分析结果。

              [root@localhost oprofile-1.1.0]# opannotate --merge=cpu -s a.out  

    /*
    * Command line: opannotate --merge=cpu -s a.out
    *
    * Interpretation of command line:
    * Output annotated source file with samples
    * Output all files
    *
    * CPU: Core 2, speed 2666.13 MHz (estimated)
    * Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 10000
    * Processes with a thread ID of 32720
    * Processes with a thread ID of all
    */
    /*
    * Total samples for file : "/root/czh/oprofile-1.1.0/test.c"
    *
    * 365 100.000 1261 100.000
    */


                  :#include <stdio.h>
                  :
                  :int fun(int s,int i)
    16 4.3836 59 4.6788     :{ /* fun total: 226 61.9178 756 59.9524 */
    6 1.6438 37 2.9342     : printf("s = %d , i = %d ",s,i);
    153 41.9178 475 37.6685  : s = s+i;
    32 8.7671 96 7.6130     : return s;
    19 5.2055 89 7.0579     :}
                  :
                  :
                  :int main()
                  :{ /* main total: 139 38.0822 505 40.0476 */
                  : int i = 0;
                  : int sum = 0;
    126 34.5205 439 34.8136  : for(;i<0x10000;i++)
    13 3.5616 66 5.2339      : sum = fun(sum,i);
                  : printf("sum = %x ",sum);
                  : return 0;
                  :}

        可以清楚的看到哪一行的代码占用的时间最多。

        注意,如果在虚拟机下运行,是不支持基于事件采样的,只能基于时间采用,但是这个采样率太低,效果很差。

        加载模块前先运行modprobe oprofile timer=1

        可以通过dmesg查看是否是以timer运行的

      15.vprobe

        找不到相关资料

      16.查看x86机器是否支持64位

        这一点可以通过查看cpu自带的寄存器内容或者/proc/cpuinfo中的内容

  • 相关阅读:
    做题经验
    4906 删数问题
    1225 八数码难题
    1005 生日礼物
    1004 四子连棋 未完成
    1008 选数 2002年NOIP全国联赛普及组
    1068 乌龟棋 2010年NOIP全国联赛提高组
    2292 图灵机游戏
    实战数据结构(9)_单链表实现多项式的相乘
    最近招两个兼职的活(PHP和JSP)
  • 原文地址:https://www.cnblogs.com/leo0000/p/5550151.html
Copyright © 2011-2022 走看看