• 【Linux调试技术】查看数据


    作者:gnuhpc
    出处:http://www.cnblogs.com/gnuhpc/

    本文首先以一个二叉树插入算法的实现作为例子说明GDB查看程序数据的相关方法,代码如下:

      1: //  bintree.c:  routines to do insert and sorted print of a binary tree

     

      2:

     

      3: #include

     

      4: #include

     

      5:

     

      6: struct node {

     

      7:    int val;             // stored value

     

      8:    struct node *left;   // ptr to smaller child

     

      9:    struct node *right;  // ptr to larger child

     

     10: };

     

     11:

     

     12: typedef struct node *nsp;

     

     13:

     

     14: nsp root;

     

     15:

     

     16: nsp makenode(int x)

     

     17: {

     

     18:    nsp tmp; 

     

     19:

     

     20:    tmp = (nsp) malloc(sizeof(struct node)); 

     

     21:    tmp->val = x; 

     

     22:    tmp->left = tmp->right = 0;

     

     23:    return tmp;

     

     24: }

     

     25:

     

     26: void insert(nsp *btp, int x)

     

     27: {

     

     28:    nsp tmp = *btp;

     

     29:

     

     30:    if (*btp == 0) {

     

     31:       *btp = makenode(x);

     

     32:       return;

     

     33:    }

     

     34:

     

     35:    while (1)

     

     36:    {

     

     37:       if (x < tmp->val) {

     

     38:

     

     39:          if (tmp->left != 0) {

     

     40:             tmp = tmp->left;

     

     41:          } else {

     

     42:             tmp->left = makenode(x);

     

     43:             break;

     

     44:          }

     

     45:

     

     46:       } else {

     

     47:

     

     48:          if (tmp->right != 0) {

     

     49:             tmp = tmp->right;

     

     50:          } else {

     

     51:             tmp->right = makenode(x);

     

     52:             break;

     

     53:          }

     

     54:

     

     55:       }

     

     56:    }

     

     57: }

     

     58:

     

     59:

     

     60: void printtree(nsp bt)

     

     61: {

     

     62:    if (bt == 0) return;

     

     63:    printtree(bt->left);

     

     64:    printf("%d/n",bt->val);

     

     65:    printtree(bt->right);

     

     66: }

     

     67:

     

     68:

     

     69: int main(int argc, char *argv[])

     

     70: {

     

     71:    root = 0;

     

     72:    for (int i = 1; i < argc; i++)

     

     73:       insert(&root, atoi(argv[i]));

     

     74:    printtree(root);

     

     75: }

     

    在调试这个二叉树插入程序的时候,我们会非常关心insert方法的执行情况,在进入那个while(1)循环后,我们可能会做以下的操作:

    (gdb) p tmp->val
    $1=12
    (gdb) p tmp->left
    $2 = (struct node *) 0x8049698
    (gdb) p tmp->right
    $3 = (struct node *) 0x0

    这个操作显得累赘又麻烦,我们可以有以下的改进措施:

    1.直接打印结构体tmp

    (gdb) p *tmp
    $4 = {val = 12, left = 0x8049698, right = 0x0}

    2.使用display命令:我们在#37设置断点,然后运行程序,待程序运行至该断点停下后使用display = disp 命令对某一个变量进行监视(之所以这样做是因为这个变量必须存在在该栈帧上,也就是说调试的时候这个变量的确被创建并且没有被销毁),程序以后只要一停止就打印这个变量的值在屏幕上:

    (gdb) disp *tmp
    1: *tmp = {val = 12, left = 0x8049698, right = 0x0}
    (gdb) c
    Continuing.
    Breakpoint 1, insert (btp=0x804967c, x=5) at bintree.c:37
    37 if (x < tmp->val) {
    1: *tmp = {val = 8, left = 0x0, right = 0x0}

    也可以使用dis disp 1使这个监视动作失效(enable disp 1则恢复),undisp 1为删除。info display为查看当前所有自动打印点相关的信息

    3.使用命令列表:在上篇中已经叙述,在此不再赘述。

    4.使用call命令:我们在代码中已经有了一个打印整个树的函数printtree,使用call命令我们可以直接利用代码中的方法进行变量监视,在每次insert完成的时候调用printtree对二叉树进行打印:

    (gdb) commands 2
    Type commands for when breakpoint 2 is hit, one per line.
    End with a line saying just "end".
    >printf "*********** current tree ***********"
    >call printtree(root)
    >end

    5.使用DDDData Window图形化表示:单击右键在root这个变量上然后选择display *root,每次在#37行停下时,在Data Window内对整个树的都有图形化表示,在左右子树上,你可以使用右键单击然后选择Display *()来显示。(Tips:你可以以--separate参数启动DDD,这样每个Window都是独立的,你可以获得更大的视野)。

    补充:

    1.打印数组:p *pointer@number_of_elements,其中number_of_elements表示显示pointer这个变量中的几个成员。另外一种方式是类型转换,例如下列程序:

      1: int *x;

     

      2: main()

     

      3: {

     

      4:    x = (int *) malloc(25*sizeof(int));

     

      5:    x[3] = 12;

     

      6: }

     

    除了可以使用:

    (gdb) p *x@25
    $1 = {0, 0, 0, 12, 0 }

    我们还可以使用:

    (gdb) p (int [25]) *x
    $2 = {0, 0, 0, 12, 0 }

    2.打印本地变量info locals,会打印当前栈帧的本地变量。

    3.以不同形式打印变量p/paramenters variable  parameters 可以是 x 表示打印变量以十六进制表示,f为浮点,ccharactersstring

    4.打印历史查看过的变量:使用$number,而只使用$表示上一个变量。

    (gdb) p tmp->left
    $1 = (struct node *) 0x80496a8
    (gdb) p *(tmp->left)
    $2 = {val = 5, left = 0x0, right = 0x0}
    (gdb) p *$1
    $3 = {val = 5, left = 0x0, right = 0x0}

    (gdb) p tmp->left
    $1 = (struct node *) 0x80496a8
    (gdb) p *$
    $2 = {val = 5, left = 0x0, right = 0x0}

    5.修改被调试程序运行时的变量值set x = 12

    6.利用自定义变量方便调试:例如,

      1: int w[4] = {12,5,8,29};

     

      2: main()

     

      3: {

     

      4:    w[2] = 88;

     

      5: }

     

    我们设置i,然后利用这个变量对这个数组进行遍历:

    (gdb) set $i = 0
    (gdb) p w[$i++]
    $1=12
    (gdb)
    $2=5
    (gdb)
    $3=88
    (gdb)
    $4=29

    7.强制类型打印

    p {type}address:address指定的内存解释为type类型(类似于强制转型,更加强)

    8.设置一些常见选项

    ·        1) set print array:打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。默认关闭

    ·        2) set print elements num-of-elements:设置GDB打印数据时显示元素的个数,缺省为200,设为0表示不限制(unlimited)

    ·        3) set print null-stop:设置GDB打印字符数组的时候,遇到NULL时停止,缺省是关闭的

    ·        4) set print pretty:设置GDB打印结构的时候,每行一个成员,并且有相应的缩进,缺省是关闭的

    ·        5) set print object:设置GDB打印多态类型的时候,打印实际的类型,缺省为关闭

    ·        6) set print static-members:设置GDB打印结构的时候,是否打印static成员,缺省是打开的

    ·        7) set print vtblGDB将用比较规整的格式来显示虚函数表,缺省是关闭的

    参考文献:
    Art of Debugging

    Linux® Debugging and Performance Tuning: Tips and Techniques

     

    作者:gnuhpc
    出处:http://www.cnblogs.com/gnuhpc/


                   作者:gnuhpc
                   出处:http://www.cnblogs.com/gnuhpc/
                   除非另有声明,本网站采用知识共享“署名 2.5 中国大陆”许可协议授权。


    分享到:

  • 相关阅读:
    windows 的文件夹映射实现
    项目管理工具
    SSM(Spring+SpringMVC+MyBatis)高并发优化思路
    高性能高可用高并发技术架构的一些理解
    你懂什么是分布式系统吗?Redis分布式锁都不会?
    使用批处理文件(*.bat)同时打多个cmd窗口
    mysql删除重复数据只保留一条
    native2ascii命令
    利用编辑距离(Edit Distance)计算两个字符串的相似度
    eclipse如何正确部署tomcat7
  • 原文地址:https://www.cnblogs.com/gnuhpc/p/2810148.html
Copyright © 2020-2023  润新知