zoukankan      html  css  js  c++  java
  • gdb调试的基本使用

    GDB调试
    启动程序准备调试
    GDB yourpram
    或者
    先输入GDB
    然后输入 file yourpram

    然后使用run或者r命令开始程序的执行,也可以使用 run parameter将参数传递给该程序

    参数列表

    命令

    命令缩写

    命令说明

    list

    l

    显示多行源代码

    break

    b

    设置断点,程序运行到断点的位置会停下来

    info

    i

    描述程序的状态

    run

    r

    开始运行程序

    display

    disp

    跟踪查看某个变量,每次停下来都显示它的值

    step

    s

    执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句

    next

    n

    执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)

    print

    p

    打印内部变量值

    continue

    c

    继续程序的运行,直到遇到下一个断点

    set var name=v

     

    设置变量的值

    start

    st

    开始执行程序,main函数的第一条语句前面停下来

    file

     

    装入需要调试的程序

    kill

    k

    终止正在调试的程序

    watch

     

    监视变量值的变化

    backtrace

    bt

    查看函数调用信息(堆栈)

    frame

    f

    查看栈帧  f n 切换到编号为n的栈

    quit

    q

    退出GDB环境

      

    //e.c
     #include <stdio.h>
    void debug(char *str)
    {
        printf("debug info :%s
    ",str );
    }
    main(int argc,char *argv[]){
        int i,j;
        j=0;
        for(i=0;i<10;i++){
            j+=5;
            printf("now a=%d
    ", j);
        }
    }

    gcc -g -o e e.c
    调试gdb e
    或者输入gdb
    然后 file e

    list 命令用法

    list命令显示多行源代码,从上次的位置开始显示,默认情况下,一次显示10行,第一次使用时,从代码起始位置显示

    gdb) list
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    main(int argc,char *argv[]){
    7        int i,j;
    8        j=0;
    9        for(i=0;i<10;i++){
    10            j+=5;
    (gdb) 

    list n显示已第n行未中心的10行代码

    (gdb) list 8
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    main(int argc,char *argv[]){
    7        int i,j;
    8        j=0;
    9        for(i=0;i<10;i++){
    10            j+=5;
    11            printf("now a=%d
    ", j);
    12        }
    (gdb) 

    list functionname显示以functionname的函数为中心的10行代码

    (gdb) list main
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    main(int argc,char *argv[]){
    7        int i,j;
    8        j=0;
    9        for(i=0;i<10;i++){
    10            j+=5;
    (gdb) 

    list - 显示刚才打印过的源代码之前的代码

    (gdb) list 10
    5    }
    6    main(int argc,char *argv[]){
    7        int i,j;
    8        j=0;
    9        for(i=0;i<10;i++){
    10            j+=5;
    11            printf("now a=%d
    ", j);
    12        }
    13    }(gdb) list -
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    (gdb) 

    断点命令break
    break location:在location位置设置断点,该位置可以为某一行,某函数名或者其它结构的地址
    GDB会在执行该位置的代码之前停下来

    gdb) list
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    main(int argc,char *argv[]){
    7        int i,j;
    8        j=0;
    9        for(i=0;i<10;i++){
    10            j+=5;
    (gdb) 
    11            printf("now a=%d
    ", j);
    12        }
    13    }(gdb) break 10
    Breakpoint 1 at 0x40050a: file e.c, line 10.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/e 
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10
    10            j+=5;
    (gdb) c
    Continuing.
    now a=5
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10
    10            j+=5;
    (gdb) c
    Continuing.
    now a=10
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10
    10            j+=5;
    (gdb) 
    View Code

    使用delete breakpoints 断点号 删除断点
    这里的断点号表示的是第几个断点,刚才执行break 10返回 reakpoint 1 at 0x40050a: file e.c, line 10.
    中的1表示该断点的标号,因此使用 delete breakpoints 1表示删除第10行所定义的断点
    clear n表示清除第n行的断点,因此clear 10等同于delete breakpoints 1
    disable/enable n表示使得编号为n的断点暂时失效或有效
    可使用info查看断点相关的信息
    info breakpoints

    gdb) info breakpoints
    No breakpoints or watchpoints.
    (gdb) break 10
    Breakpoint 2 at 0x40050a: file e.c, line 10.
    (gdb) break 9
    Breakpoint 3 at 0x400501: file e.c, line 9.
    (gdb) info breakpoints
    Num     Type           Disp Enb Address            What
    2       breakpoint     keep y   0x000000000040050a in main at e.c:10
    3       breakpoint     keep y   0x0000000000400501 in main at e.c:9

    display命令
    查看参数的值

    (gdb) break 10
    Breakpoint 1 at 0x40050a: file e.c, line 10.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/e 
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10
    10            j+=5;
    (gdb) display j
    1: j = 0
    (gdb) c
    Continuing.
    now a=5
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe548) at e.c:10
    10            j+=5;
    1: j = 5
    (gdb) display
    1: j = 5
    (gdb) display i
    2: i = 1
    (gdb) display j
    3: j = 5
    (gdb) display j*2
    4: j*2 = 10
    (gdb) info display
    Auto-display expressions now in effect:
    Num Enb Expression
    4:   y  j*2
    3:   y  j
    2:   y  i
    1:   y  j
    View Code

    也可以使用disable,enable,delete,info命令修改及查看其状态,用法与对断点的一样

    step及next命令
    step可使得程序逐条执行,即执行完一条语句然后在吓一跳语句前停下来,等待用户的命令
    一般使用step命令是,可使用display或者watch命令查看变量的变化,从而判断程序行为是否符合要求
    当下一条指令为函数时,s进入函数内部,在其第一条语句前停下来
    step n,next n 表示连续但不执行n条指令,如果期间遇到断点,则停下来

    (gdb) list
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    
    7    main(int argc,char *argv[]){
    8        int i,j;
    9        j=0;
    10        for(i=0;i<10;i++){
    (gdb) 
    11            j+=5;
    12            printf("now j=%d
    ", j);
    13            debug("x=======x");
    14        }
    15    }(gdb) 
    Line number 16 out of range; e.c has 15 lines.
    (gdb) break 11
    Breakpoint 1 at 0x40050a: file e.c, line 11.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/e1 
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:11
    11            j+=5;
    (gdb) s
    12            printf("now j=%d
    ", j);
    (gdb) s
    __printf (format=0x400648 "now j=%d
    ") at printf.c:30
    30    {
    (gdb) bt
    #0  __printf (format=0x400648 "now j=%d
    ") at printf.c:30
    #1  0x0000000000400525 in main (argc=1, argv=0x7fffffffe538) at e.c:12
    (gdb) n
    34      va_start (arg, format);
    (gdb) n
    35      done = vfprintf (stdout, format, arg);
    (gdb) n
    now j=5
    39    }
    (gdb) bt
    #0  __printf (format=<value optimized out>) at printf.c:39
    #1  0x0000000000400525 in main (argc=1, argv=0x7fffffffe538) at e.c:12
    (gdb) n
    main (argc=1, argv=0x7fffffffe538) at e.c:13
    13            debug("x=======x");
    (gdb) n
    debug info :x=======x
    10        for(i=0;i<10;i++){
    (gdb) s
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:11
    11            j+=5;
    (gdb) s
    12            printf("now j=%d
    ", j);
    (gdb) n
    now j=10
    13            debug("x=======x");
    (gdb) n
    debug info :x=======x
    10        for(i=0;i<10;i++){
    (gdb) 
    View Code

    watch
    watch可设置观察点(watchpoint)。使用观察点可以使得当某表达式的值发生变化时,程序暂停执行。
    执行该命令前,必须保证程序已经运行

    (gdb) list 
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    
    7    main(int argc,char *argv[]){
    8        int i,j;
    9        j=0;
    10        for(i=0;i<10;i++){
    (gdb) 
    11            j+=5;
    12            printf("now j=%d
    ", j);
    13            debug("x=======x");
    14        }
    15    }(gdb) 
    Line number 16 out of range; e.c has 15 lines.
    (gdb) b main
    Breakpoint 1 at 0x4004fa: file e.c, line 9.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/e1 
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:9
    9        j=0;
    (gdb) watch j
    Hardware watchpoint 2: j
    (gdb) c
    Continuing.
    Hardware watchpoint 2: j
    
    Old value = 0
    New value = 5
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) c
    Continuing.
    now j=5
    debug info :x=======x
    Hardware watchpoint 2: j
    
    Old value = 5
    New value = 10
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    View Code

    print命令

    (gdb) list
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    
    7    main(int argc,char *argv[]){
    8        int i,j;
    9        j=0;
    10        for(i=0;i<10;i++){
    (gdb) 
    11            j+=5;
    12            printf("now j=%d
    ", j);
    13            debug("x=======x");
    14        }
    15    }(gdb) 
    Line number 16 out of range; e.c has 15 lines.
    (gdb) break 12
    Breakpoint 1 at 0x40050e: file e.c, line 12.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/e1 
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) p j
    $1 = 5
    (gdb) c
    Continuing.
    now j=5
    debug info :x=======x
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) p i,j
    $2 = 10
    (gdb) p j
    $3 = 10
    (gdb) 
    View Code

    set var name=value

    set args 可指定运行时参数(当main函数需要参数时 如:set args 10 20 30 40 50)

    show args 命令可以查看设置好的运行参数


    在程序运行中动态改变变量的值

    (gdb) list
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    
    7    main(int argc,char *argv[]){
    8        int i,j;
    9        j=0;
    10        for(i=0;i<10;i++){
    (gdb) 
    11            j+=5;
    12            printf("now j=%d
    ", j);
    13            debug("x=======x");
    14        }
    15    }(gdb) 
    Line number 16 out of range; e.c has 15 lines.
    (gdb) break main
    Breakpoint 1 at 0x4004fa: file e.c, line 9.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/e1 
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:9
    9        j=0;
    (gdb) watch i
    Hardware watchpoint 2: i
    (gdb) watch j
    Hardware watchpoint 3: j
    (gdb) c
    Continuing.
    Hardware watchpoint 3: j
    
    Old value = 0
    New value = 5
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) c
    Continuing.
    now j=5
    debug info :x=======x
    Hardware watchpoint 2: i
    
    Old value = 0
    New value = 1
    0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10
    10        for(i=0;i<10;i++){
    (gdb) c
    Continuing.
    Hardware watchpoint 3: j
    
    Old value = 5
    New value = 10
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) c
    Continuing.
    now j=10
    debug info :x=======x
    Hardware watchpoint 2: i
    
    Old value = 1
    New value = 2
    0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10
    10        for(i=0;i<10;i++){
    (gdb) c
    Continuing.
    Hardware watchpoint 3: j
    
    Old value = 10
    New value = 15
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) c
    Continuing.
    now j=15
    debug info :x=======x
    Hardware watchpoint 2: i
    
    Old value = 2
    New value = 3
    0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10
    10        for(i=0;i<10;i++){
    (gdb) c
    Continuing.
    Hardware watchpoint 3: j
    
    Old value = 15
    New value = 20
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) c
    Continuing.
    now j=20
    debug info :x=======x
    Hardware watchpoint 2: i
    
    Old value = 3
    New value = 4
    0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10
    10        for(i=0;i<10;i++){
    (gdb) set var i=8
    (gdb) c
    Continuing.
    Hardware watchpoint 3: j
    
    Old value = 20
    New value = 25
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) c
    Continuing.
    now j=25
    debug info :x=======x
    Hardware watchpoint 2: i
    
    Old value = 8
    New value = 9
    0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10
    10        for(i=0;i<10;i++){
    (gdb) c
    Continuing.
    Hardware watchpoint 3: j
    
    Old value = 25
    New value = 30
    main (argc=1, argv=0x7fffffffe538) at e.c:12
    12            printf("now j=%d
    ", j);
    (gdb) c
    Continuing.
    now j=30
    debug info :x=======x
    Hardware watchpoint 2: i
    
    Old value = 9
    New value = 10
    0x0000000000400533 in main (argc=1, argv=0x7fffffffe538) at e.c:10
    10        for(i=0;i<10;i++){
    (gdb) c
    Continuing.
    
    Watchpoint 2 deleted because the program has left the block in
    which its expression is valid.
    
    Watchpoint 3 deleted because the program has left the block in
    which its expression is valid.
    __libc_start_main (main=0x4004eb <main>, argc=1, ubp_av=0x7fffffffe538, init=<value optimized out>, fini=<value optimized out>, rtld_fini=<value optimized out>, 
        stack_end=0x7fffffffe528) at libc-start.c:258
    258      exit (result);
    (gdb) c
    Continuing.
    
    Program exited with code 026.
    View Code

    函数调用相关的
    backtrace
    可使用frame 查看堆栈中某一帧的信息

    (gdb) list
    1    #include <stdio.h>
    2    void debug(char *str)
    3    {
    4        printf("debug info :%s
    ",str );
    5    }
    6    
    7    main(int argc,char *argv[]){
    8        int i,j;
    9        j=0;
    10        for(i=0;i<10;i++){
    (gdb) 
    11            j+=5;
    12            printf("now j=%d
    ", j);
    13            debug("x=======x");
    14        }
    15    }(gdb) 
    Line number 16 out of range; e.c has 15 lines.
    (gdb) b 13
    Breakpoint 1 at 0x400525: file e.c, line 13.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/e1 
    now j=5
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:13
    13            debug("x=======x");
    (gdb) s
    debug (str=0x400652 "x=======x") at e.c:4
    4        printf("debug info :%s
    ",str );
    (gdb) bt
    #0  debug (str=0x400652 "x=======x") at e.c:4
    #1  0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13
    (gdb) s
    __printf (format=0x400638 "debug info :%s
    ") at printf.c:30
    30    {
    (gdb) bt
    #0  __printf (format=0x400638 "debug info :%s
    ") at printf.c:30
    #1  0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4
    #2  0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13
    (gdb) s
    34      va_start (arg, format);
    (gdb) bt
    #0  __printf (format=0x400638 "debug info :%s
    ") at printf.c:34
    #1  0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4
    #2  0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13
    (gdb) s
    35      done = vfprintf (stdout, format, arg);
    (gdb) s
    _IO_vfprintf_internal (s=0x333a58f040, format=0x400638 "debug info :%s
    ", ap=0x7fffffffe330) at vfprintf.c:236
    236      int save_errno = errno;
    (gdb) bt
    #0  _IO_vfprintf_internal (s=0x333a58f040, format=0x400638 "debug info :%s
    ", ap=0x7fffffffe330) at vfprintf.c:236
    #1  0x000000333a24effa in __printf (format=<value optimized out>) at printf.c:35
    #2  0x00000000004004e9 in debug (str=0x400652 "x=======x") at e.c:4
    #3  0x000000000040052f in main (argc=1, argv=0x7fffffffe538) at e.c:13
    (gdb) c
    Continuing.
    debug info :x=======x
    now j=10
    
    Breakpoint 1, main (argc=1, argv=0x7fffffffe538) at e.c:13
    13            debug("x=======x");
    (gdb) bt
    #0  main (argc=1, argv=0x7fffffffe538) at e.c:13
    View Code

     GDB段错误调试

    所谓段错误就是对内存的非法访问
    采用GDB调试段错误有2种方法
    1.在GDB中运行目标程序,当发生段错误时,GDB中运行的程序会自动停下来
    2.直接运行目标程序,使其在发生段错误时产生内存转储(core dump)文件,GDB对该文件进行调试

    abort.c

    #include <stdio.h>
    #include <stdlib.h>
    
    void recurse(void)
    {
        static int i;
        if( ++i == 3)
            abort();
        else
            recurse();
    }
    int main(int argc,char ** argv){
        recurse();
    }
    gcc -g -o abort abort.c
    使用gdb调试
    Line number 15 out of range; abort.c has 14 lines.
    (gdb) r
    Starting program: /mnt/hgfs/www/c/gcc/abort 
    
    Program received signal SIGABRT, Aborted.
    0x000000333a232495 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
    64      return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig);
    (gdb) bt
    #0  0x000000333a232495 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
    #1  0x000000333a233c75 in abort () at abort.c:92
    #2  0x00000000004004e7 in recurse () at abort.c:8
    #3  0x00000000004004ec in recurse () at abort.c:10
    #4  0x00000000004004ec in recurse () at abort.c:10
    #5  0x0000000000400502 in main (argc=1, argv=0x7fffffffe528) at abort.c:13
    显示在recurse函数调用了3次后调用了abort函数,产生段错误

    使用内存转储文件

    ulimit -a 

    [root@centos1 gcc]# ulimit -a 
    core file size          (blocks, -c) 0
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 7331
    max locked memory       (kbytes, -l) 64
    max memory size         (kbytes, -m) unlimited
    open files                      (-n) 1024
    pipe size            (512 bytes, -p) 8
    POSIX message queues     (bytes, -q) 819200
    real-time priority              (-r) 0
    stack size              (kbytes, -s) 10240
    cpu time               (seconds, -t) unlimited
    max user processes              (-u) 7331
    virtual memory          (kbytes, -v) unlimited
    file locks                      (-x) unlimited
    core file size 此时是0

    ulimit -c unlimited  设置为不受限制

    执行 ./abort 产生内存转储文件
    ls 可看到一个名为core且以进程号为后缀的文件

    core.6289
    gdb abort core.6289
    bt
    方法同上一个gdb调试

  • 相关阅读:
    第一周例行报告
    2018091-2 博客作业
    jQuery $.post $.ajax用法
    HTML ul、li 属性介绍
    PHP日期格式转时间戳
    php字符串与字符替换函数
    Linux内核参数
    ifconfig-dropped
    mysql_load_data及权限管理
    加快mysql导入导出速度
  • 原文地址:https://www.cnblogs.com/HKUI/p/8955443.html
Copyright © 2011-2022 走看看